File apache_exporter-1.0.0.obscpio of Package golang-github-lusitaniae-apache_exporter.32207

07070100000000000041ED000000000000000000000002649954C000000000000000000000000000000000000000000000002000000000apache_exporter-1.0.0/.circleci07070100000001000081A4000000000000000000000001649954C000000237000000000000000000000000000000000000002B00000000apache_exporter-1.0.0/.circleci/config.yml---
# Prometheus has switched to GitHub action.
# Circle CI is not disabled repository-wise so that previous pull requests
# continue working.
# This file does not generate any CircleCI workflow.

version: 2.1

executors:
  golang:
    docker:
      - image: busybox

jobs:
  noopjob:
    executor: golang

    steps:
      - run:
          command: "true"

workflows:
  version: 2
  prometheus:
    jobs:
      - noopjob
    triggers:
      - schedule:
          cron: "0 0 30 2 *"
          filters:
            branches:
              only:
                - main
07070100000002000041ED000000000000000000000003649954C000000000000000000000000000000000000000000000001E00000000apache_exporter-1.0.0/.github07070100000003000081A4000000000000000000000001649954C00000006E000000000000000000000000000000000000002D00000000apache_exporter-1.0.0/.github/dependabot.ymlversion: 2
updates:
  - package-ecosystem: "gomod"
    directory: "/"
    schedule:
      interval: "monthly"
07070100000004000041ED000000000000000000000002649954C000000000000000000000000000000000000000000000002800000000apache_exporter-1.0.0/.github/workflows07070100000005000081A4000000000000000000000001649954C000000A08000000000000000000000000000000000000002F00000000apache_exporter-1.0.0/.github/workflows/ci.yml---
name: CI
on:
  pull_request:
  push:
jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    # Whenever the Go version is updated here, .promu.yml
    # should also be updated.
    container:
      image: quay.io/prometheus/golang-builder:1.19-base
    steps:
      - uses: actions/checkout@v3
      - uses: prometheus/promci@v0.0.2
      - uses: ./.github/promci/actions/setup_environment
      - run: make

  build:
    name: Build
    runs-on: ubuntu-latest
    strategy:
      matrix:
        thread: [ 0, 1, 2 ]
    steps:
      - uses: actions/checkout@v3
      - uses: prometheus/promci@v0.0.2
      - uses: ./.github/promci/actions/build
        with:
          parallelism: 3
          thread: ${{ matrix.thread }}

  golangci:
    name: golangci-lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
      - name: Install Go
        uses: actions/setup-go@v3
        with:
          go-version: '<1.19'
      - name: Lint
        uses: golangci/golangci-lint-action@v3.2.0
        with:
          version: v1.51.1

  # modified from the original as this repo still using master, insteead of main
  publish_master:
    name: Publish master branch artifacts
    runs-on: ubuntu-latest
    needs: [test, build]
    if: github.event_name == 'push' && github.event.ref == 'refs/heads/master'
    steps:
      - uses: actions/checkout@v3
      - uses: prometheus/promci@v0.0.2
      - uses: ./.github/promci/actions/publish_main
        with:
          docker_hub_organization: lusotycoon
          docker_hub_login: ${{ secrets.docker_hub_login }}
          docker_hub_password: ${{ secrets.docker_hub_password }}
          quay_io_organization: lusitaniae
          quay_io_login: ${{ secrets.quay_io_login }}
          quay_io_password: ${{ secrets.quay_io_password }}

  publish_release:
    name: Publish release arfefacts
    runs-on: ubuntu-latest
    needs: [test, build]
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
    steps:
      - uses: actions/checkout@v3
      - uses: prometheus/promci@v0.0.2
      - uses: ./.github/promci/actions/publish_release
        with:
          docker_hub_organization: lusotycoon
          docker_hub_login: ${{ secrets.docker_hub_login }}
          docker_hub_password: ${{ secrets.docker_hub_password }}
          quay_io_organization: lusitaniae
          quay_io_login: ${{ secrets.quay_io_login }}
          quay_io_password: ${{ secrets.quay_io_password }}
          github_token: ${{ secrets.PROMBOT_GITHUB_TOKEN }}
07070100000006000081A4000000000000000000000001649954C000000027000000000000000000000000000000000000002100000000apache_exporter-1.0.0/.gitignore.idea/*
bin/*
vendor/
apache_exporter

07070100000007000081A4000000000000000000000001649954C000000086000000000000000000000000000000000000002400000000apache_exporter-1.0.0/.golangci.yml# Run only staticcheck for now. Additional linters will be enabled one-by-one.
linters:
  enable:
  - staticcheck
  disable-all: true
07070100000008000081A4000000000000000000000001649954C00000028B000000000000000000000000000000000000002100000000apache_exporter-1.0.0/.promu.ymlgo:
    # Whenever the Go version is updated here,
    # .circle/config.yml should also be updated.
    version: 1.19
    # cgo: false
repository:
    path: github.com/Lusitaniae/apache_exporter
build:
    flags: -a -tags netgo
    ldflags: |
        -X github.com/prometheus/common/version.Version={{.Version}}
        -X github.com/prometheus/common/version.Revision={{.Revision}}
        -X github.com/prometheus/common/version.Branch={{.Branch}}
        -X github.com/prometheus/common/version.BuildUser={{user}}@{{host}}
        -X github.com/prometheus/common/version.BuildDate={{date "20060102-15:04:05"}}
tarball:
    files:
        - LICENSE
07070100000009000081A4000000000000000000000001649954C00000017C000000000000000000000000000000000000002000000000apache_exporter-1.0.0/.yamllint---
extends: default

rules:
  braces:
    max-spaces-inside: 1
    level: error
  brackets:
    max-spaces-inside: 1
    level: error
  commas: disable
  comments: disable
  comments-indentation: disable
  document-start: disable
  indentation:
    spaces: consistent
    indent-sequences: consistent
  line-length: disable
  truthy:
    ignore: |
      .github/workflows/ci.yml
0707010000000A000081A4000000000000000000000001649954C000000152000000000000000000000000000000000000002100000000apache_exporter-1.0.0/DockerfileARG ARCH="amd64"
ARG OS="linux"
FROM quay.io/prometheus/busybox-${OS}-${ARCH}:latest
LABEL maintainer="https://github.com/Lusitaniae, https://github.com/roidelapluie"

ARG ARCH="amd64"
ARG OS="linux"
COPY .build/${OS}-${ARCH}/apache_exporter /bin/apache_exporter

EXPOSE      9117
USER        nobody
ENTRYPOINT  [ "/bin/apache_exporter" ]0707010000000B000081A4000000000000000000000001649954C000000433000000000000000000000000000000000000001E00000000apache_exporter-1.0.0/LICENSEThe MIT License (MIT)

Copyright (c) 2015 neezgee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

0707010000000C000081A4000000000000000000000001649954C00000052F000000000000000000000000000000000000001F00000000apache_exporter-1.0.0/Makefile# Copyright 2015 The Prometheus Authors
# Licensed 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.

# Needs to be defined before including Makefile.common to auto-generate targets
DOCKER_ARCHS ?= amd64 armv7 arm64 ppc64le s390x
DOCKER_IMAGE_NAME ?= apache-exporter

all:: vet checkmetrics common-all

include Makefile.common

PROMETHEUS_VERSION=2.39.1
PROMTOOL ?= /tmp/prometheus-$(PROMETHEUS_VERSION).linux-amd64/promtool

.PHONY: checkmetrics
checkmetrics:
	@echo ">> checking metrics for correctness"
	if ! test -x $(PROMTOOL); then curl -sL -o - https://github.com/prometheus/prometheus/releases/download/v$(PROMETHEUS_VERSION)/prometheus-$(PROMETHEUS_VERSION).linux-amd64.tar.gz | tar -C /tmp -xzf - prometheus-$(PROMETHEUS_VERSION).linux-amd64/promtool; fi
	for file in test/*.metrics; do $(PROMTOOL) check metrics < $$file || exit 1; done
0707010000000D000081A4000000000000000000000001649954C00000292B000000000000000000000000000000000000002600000000apache_exporter-1.0.0/Makefile.common# Copyright 2018 The Prometheus Authors
# Licensed 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.


# A common Makefile that includes rules to be reused in different prometheus projects.
# !!! Open PRs only against the prometheus/prometheus/Makefile.common repository!

# Example usage :
# Create the main Makefile in the root project directory.
# include Makefile.common
# customTarget:
# 	@echo ">> Running customTarget"
#

# Ensure GOBIN is not set during build so that promu is installed to the correct path
unexport GOBIN

GO           ?= go
GOFMT        ?= $(GO)fmt
FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH)))
GOOPTS       ?=
GOHOSTOS     ?= $(shell $(GO) env GOHOSTOS)
GOHOSTARCH   ?= $(shell $(GO) env GOHOSTARCH)

GO_VERSION        ?= $(shell $(GO) version)
GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION))
PRE_GO_111        ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.')

GOVENDOR :=
GO111MODULE :=
ifeq (, $(PRE_GO_111))
	ifneq (,$(wildcard go.mod))
		# Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI).
		GO111MODULE := on

		ifneq (,$(wildcard vendor))
			# Always use the local vendor/ directory to satisfy the dependencies.
			GOOPTS := $(GOOPTS) -mod=vendor
		endif
	endif
else
	ifneq (,$(wildcard go.mod))
		ifneq (,$(wildcard vendor))
$(warning This repository requires Go >= 1.11 because of Go modules)
$(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)')
		endif
	else
		# This repository isn't using Go modules (yet).
		GOVENDOR := $(FIRST_GOPATH)/bin/govendor
	endif
endif
PROMU        := $(FIRST_GOPATH)/bin/promu
pkgs          = ./...

ifeq (arm, $(GOHOSTARCH))
	GOHOSTARM ?= $(shell GOARM= $(GO) env GOARM)
	GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)v$(GOHOSTARM)
else
	GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)
endif

GOTEST := $(GO) test
GOTEST_DIR :=
ifneq ($(CIRCLE_JOB),)
ifneq ($(shell which gotestsum),)
	GOTEST_DIR := test-results
	GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml --
endif
endif

PROMU_VERSION ?= 0.13.0
PROMU_URL     := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz

GOLANGCI_LINT :=
GOLANGCI_LINT_OPTS ?=
GOLANGCI_LINT_VERSION ?= v1.51.1
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64.
# windows isn't included here because of the path separator being different.
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
	ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386))
		# If we're in CI and there is an Actions file, that means the linter
		# is being run in Actions, so we don't need to run it here.
		ifeq (,$(CIRCLE_JOB))
			GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint
		else ifeq (,$(wildcard .github/workflows/golangci-lint.yml))
			GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint
		endif
	endif
endif

PREFIX                  ?= $(shell pwd)
BIN_DIR                 ?= $(shell pwd)
DOCKER_IMAGE_TAG        ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
DOCKERFILE_PATH         ?= ./Dockerfile
DOCKERBUILD_CONTEXT     ?= ./
DOCKER_REPO             ?= prom

DOCKER_ARCHS            ?= amd64

BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS))
PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS))
TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS))

ifeq ($(GOHOSTARCH),amd64)
        ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows))
                # Only supported on amd64
                test-flags := -race
        endif
endif

# This rule is used to forward a target like "build" to "common-build".  This
# allows a new "build" target to be defined in a Makefile which includes this
# one and override "common-build" without override warnings.
%: common-% ;

.PHONY: common-all
common-all: precheck style check_license lint yamllint unused build test

.PHONY: common-style
common-style:
	@echo ">> checking code style"
	@fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \
	if [ -n "$${fmtRes}" ]; then \
		echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \
		echo "Please ensure you are using $$($(GO) version) for formatting code."; \
		exit 1; \
	fi

.PHONY: common-check_license
common-check_license:
	@echo ">> checking license header"
	@licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \
               awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \
       done); \
       if [ -n "$${licRes}" ]; then \
               echo "license header checking failed:"; echo "$${licRes}"; \
               exit 1; \
       fi

.PHONY: common-deps
common-deps:
	@echo ">> getting dependencies"
ifdef GO111MODULE
	GO111MODULE=$(GO111MODULE) $(GO) mod download
else
	$(GO) get $(GOOPTS) -t ./...
endif

.PHONY: update-go-deps
update-go-deps:
	@echo ">> updating Go dependencies"
	@for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \
		$(GO) get -d $$m; \
	done
	GO111MODULE=$(GO111MODULE) $(GO) mod tidy
ifneq (,$(wildcard vendor))
	GO111MODULE=$(GO111MODULE) $(GO) mod vendor
endif

.PHONY: common-test-short
common-test-short: $(GOTEST_DIR)
	@echo ">> running short tests"
	GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs)

.PHONY: common-test
common-test: $(GOTEST_DIR)
	@echo ">> running all tests"
	GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs)

$(GOTEST_DIR):
	@mkdir -p $@

.PHONY: common-format
common-format:
	@echo ">> formatting code"
	GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs)

.PHONY: common-vet
common-vet:
	@echo ">> vetting code"
	GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs)

.PHONY: common-lint
common-lint: $(GOLANGCI_LINT)
ifdef GOLANGCI_LINT
	@echo ">> running golangci-lint"
ifdef GO111MODULE
# 'go list' needs to be executed before staticcheck to prepopulate the modules cache.
# Otherwise staticcheck might fail randomly for some reason not yet explained.
	GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null
	GO111MODULE=$(GO111MODULE) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs)
else
	$(GOLANGCI_LINT) run $(pkgs)
endif
endif

.PHONY: common-yamllint
common-yamllint:
	@echo ">> running yamllint on all YAML files in the repository"
ifeq (, $(shell which yamllint))
	@echo "yamllint not installed so skipping"
else
	yamllint .
endif

# For backward-compatibility.
.PHONY: common-staticcheck
common-staticcheck: lint

.PHONY: common-unused
common-unused: $(GOVENDOR)
ifdef GOVENDOR
	@echo ">> running check for unused packages"
	@$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages'
else
ifdef GO111MODULE
	@echo ">> running check for unused/missing packages in go.mod"
	GO111MODULE=$(GO111MODULE) $(GO) mod tidy
ifeq (,$(wildcard vendor))
	@git diff --exit-code -- go.sum go.mod
else
	@echo ">> running check for unused packages in vendor/"
	GO111MODULE=$(GO111MODULE) $(GO) mod vendor
	@git diff --exit-code -- go.sum go.mod vendor/
endif
endif
endif

.PHONY: common-build
common-build: promu
	@echo ">> building binaries"
	GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES)

.PHONY: common-tarball
common-tarball: promu
	@echo ">> building release tarball"
	$(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR)

.PHONY: common-docker $(BUILD_DOCKER_ARCHS)
common-docker: $(BUILD_DOCKER_ARCHS)
$(BUILD_DOCKER_ARCHS): common-docker-%:
	docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \
		-f $(DOCKERFILE_PATH) \
		--build-arg ARCH="$*" \
		--build-arg OS="linux" \
		$(DOCKERBUILD_CONTEXT)

.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS)
common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
	docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)"

DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION)))
.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS)
common-docker-tag-latest: $(TAG_DOCKER_ARCHS)
$(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
	docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"
	docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"

.PHONY: common-docker-manifest
common-docker-manifest:
	DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(DOCKER_IMAGE_TAG))
	DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)"

.PHONY: promu
promu: $(PROMU)

$(PROMU):
	$(eval PROMU_TMP := $(shell mktemp -d))
	curl -s -L $(PROMU_URL) | tar -xvzf - -C $(PROMU_TMP)
	mkdir -p $(FIRST_GOPATH)/bin
	cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu
	rm -r $(PROMU_TMP)

.PHONY: proto
proto:
	@echo ">> generating code from proto files"
	@./scripts/genproto.sh

ifdef GOLANGCI_LINT
$(GOLANGCI_LINT):
	mkdir -p $(FIRST_GOPATH)/bin
	curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_LINT_VERSION)/install.sh \
		| sed -e '/install -d/d' \
		| sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION)
endif

ifdef GOVENDOR
.PHONY: $(GOVENDOR)
$(GOVENDOR):
	GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor
endif

.PHONY: precheck
precheck::

define PRECHECK_COMMAND_template =
precheck:: $(1)_precheck

PRECHECK_COMMAND_$(1) ?= $(1) $$(strip $$(PRECHECK_OPTIONS_$(1)))
.PHONY: $(1)_precheck
$(1)_precheck:
	@if ! $$(PRECHECK_COMMAND_$(1)) 1>/dev/null 2>&1; then \
		echo "Execution of '$$(PRECHECK_COMMAND_$(1))' command failed. Is $(1) installed?"; \
		exit 1; \
	fi
endef
0707010000000E000081A4000000000000000000000001649954C000002128000000000000000000000000000000000000002000000000apache_exporter-1.0.0/README.md
# Apache Exporter for Prometheus [![Build Status][buildstatus]][circleci]

[![GitHub release](https://img.shields.io/github/release/Lusitaniae/apache_exporter.svg)][release]
![GitHub Downloads](https://img.shields.io/github/downloads/Lusitaniae/apache_exporter/total.svg)
[![Docker Repository on Quay](https://quay.io/repository/Lusitaniae/apache-exporter/status)][quay]
[![Docker Pulls](https://img.shields.io/docker/pulls/lusotycoon/apache-exporter.svg?maxAge=604800)][hub]

Exports apache mod_status statistics via HTTP for Prometheus consumption.

With working golang environment it can be built with `go get`.  There is a [good article](https://machineperson.github.io/monitoring/2016/01/04/exporting-apache-metrics-to-prometheus.html) with build HOWTO and usage example.

Help on flags:

<pre>
  -h, --[no-]help                Show context-sensitive help (also try
                                 --help-long and --help-man).
      --telemetry.endpoint="/metrics"
                                 Path under which to expose metrics.
      --scrape_uri="http://localhost/server-status/?auto"
                                 URI to apache stub status page.
      --host_override=""         Override for HTTP Host header; empty string for
                                 no override.
      --[no-]insecure            Ignore server certificate if using https.
      --custom_headers     Adds custom headers to the collector.
      --[no-]web.systemd-socket  Use systemd socket activation listeners instead
                                 of port listeners (Linux only).
      --web.listen-address=:9117 ...
                                 Addresses on which to expose metrics and web
                                 interface. Repeatable for multiple addresses.
      --web.config.file=""       [EXPERIMENTAL] Path to configuration file that
                                 can enable TLS or authentication.
      --log.level=info           Only log messages with the given severity or
                                 above. One of: [debug, info, warn, error]
      --log.format=logfmt        Output format of log messages. One of: [logfmt,
                                 json]
      --[no-]version             Show application version.

</pre>

Tested on Apache 2.2 and Apache 2.4.

 If your server-status page is secured by http auth, add the credentials to the scrape URL following this example:

```
http://user:password@localhost/server-status?auto
```

Override host name by runnning
```
./apache_exporter --host_override=example.com
```

# Using Docker

## Use ```compose.yml```
- Requires Docker CE
- Does not build from source, but rather pulls from registry only
1. Edit compose.yml if needed (Maybe to change server-status endpoint)
2. ```docker compose up```

### OR
## Build the compatible binary
To make sure that exporter binary created by build job is suitable to run on busybox environment, generate the binary using Makefile definition. Inside project directory run:
```
make
```
*Please be aware that binary generated using `go get` or `go build` with defaults may not work in busybox/alpine base images.*

Another option is to use a docker go container to generate the binary.

Pick an appropriate go image from https://hub.docker.com/_/golang. Inside the project directory run:
```
docker run --rm -v <project home>:/usr/local/go/src/github.com/Lusitaniae/apache_exporter -w /usr/local/go/src/github.com/Lusitaniae/apache_exporter <go docker image name> make
```

## Build image

Run the following commands from the project root directory.

```
docker build -t apache_exporter .
```

## Run

```
docker run -d -p 9117:9117 apache_exporter \
  --scrape_uri="https://your.server.com/server-status?auto"
```

## Collectors

Apache metrics:

```
# HELP apache_accesses_total Current total apache accesses (*)
# TYPE apache_accesses_total counter
# HELP apache_scoreboard Apache scoreboard statuses
# TYPE apache_scoreboard gauge
# HELP apache_sent_kilobytes_total Current total kbytes sent (*)
# TYPE apache_sent_kilobytes_total counter
# HELP apache_cpu_load CPU Load (*)
# TYPE apache_cpu_load gauge
# HELP apache_up Could the apache server be reached
# TYPE apache_up gauge
# HELP apache_uptime_seconds_total Current uptime in seconds (*)
# TYPE apache_uptime_seconds_total counter
# HELP apache_workers Apache worker statuses
# TYPE apache_workers gauge
# HELP apache_version Apache server version
# TYPE apache_version gauge
# HELP apache_duration_ms_total Total duration of all registered requests
# TYPE apache_duration_ms_total gauge
```

Metrics marked '(*)' are only available if ExtendedStatus is On in apache webserver configuration. In version 2.3.6, loading mod_status will toggle ExtendedStatus On by default.

## FAQ

Q. Can I change the Dockerfile?

A. In short no, it's not meant for end users. It's part of the CI/CD pipeline in which promu is cross building the exporter for all architectures and packaging them into a Docker image.

Q. Can I run this exporter on different architectures (ARM)?

A. This exporter is cross compiled to all architectures using [promu](https://github.com/prometheus/promu) by running `promu crossbuild`. You can find the resulting artifacts in the release page (Github) or docker images in [Quay](https://quay.io/repository/Lusitaniae/apache-exporter) or [Docker](https://hub.docker.com/r/lusotycoon/apache-exporter/).

Q. Is there a Grafana dashboard for this exporter?

A. There's a 3rd party dashboard [here](https://grafana.com/dashboards/3894) which seems to work.
Also [monitoring-mixin](https://monitoring.mixins.dev/) (dashboard+prometheus alerts) is available [here](https://github.com/grafana/jsonnet-libs/tree/master/apache-http-mixin).

Q. Can you add additional metrics such as reqpersec, bytespersec and bytesperreq?

A. In line with the [best practices](https://prometheus.io/docs/instrumenting/writing_exporters/#drop-less-useful-statistics), the exporter only provides the totals and you should derive rates using [PromQL](https://prometheus.io/docs/prometheus/latest/querying/basics/).

>   Like that:
>   - `ReqPerSec` : `rate(apache_accesses_total[5m])`
>   - `BytesPerSec`: `rate(apache_sent_kilobytes_total[5m])`
>   - `BytesPerReq`: BytesPerSec / ReqPerSec

Q. Can I monitor multiple Apache instances?

A. In line with the [best practices](https://prometheus.io/docs/instrumenting/writing_exporters/#deployment), the answer is no. *Each process being monitored should be accompanied by **one** exporter*.

We suggest automating configuration and deployment using your favorite tools, e.g. Ansible/Chef/Kubernetes.

Q. Its not working! Apache_up shows as 0

A. When apache_up reports 0 it means the exporter is running however it is not able to connect to Apache.

Do you have this (or similar) configuration uncommented in your Apache instance?
```
<Location "/server-status">
    SetHandler server-status
    Require host example.com
</Location>
```
As documented at
https://httpd.apache.org/docs/2.4/mod/mod_status.html

Are you able to see the stats, if you run this from the Apache instance?

`curl localhost/server-status?auto`

If you run the exporter manually, do you see any errors?

`./apache_exporter`

Please include all this information if you still have issues when creating an issue.

Q. There seem to be missing metrics! I can only see apache_up and apache_cpuload.

A. Make sure that you add `?auto` at the end of the scrape_uri.



## TLS and basic authentication

Apache Exporter supports TLS and basic authentication. This enables better
control of the various HTTP endpoints.

To use TLS and/or basic authentication, you need to pass a configuration file
using the `--web.config` parameter (see above at help on flags). The format of the file is described
[in the exporter-toolkit repository](https://github.com/prometheus/exporter-toolkit/blob/master/docs/web-configuration.md).

Note that the TLS and basic authentication settings affect all HTTP endpoints:
/metrics for scraping, /probe for probing, and the web UI.


## Author

The exporter was originally created by [neezgee](https://github.com/neezgee).


[buildstatus]: https://circleci.com/gh/Lusitaniae/apache_exporter/tree/master.svg?style=shield
[quay]: https://quay.io/repository/Lusitaniae/apache-exporter
[circleci]: https://circleci.com/gh/Lusitaniae/apache_exporter
[hub]: https://hub.docker.com/r/lusotycoon/apache-exporter/
[release]: https://github.com/Lusitaniae/apache_exporter/releases/latest
0707010000000F000081A4000000000000000000000001649954C000000006000000000000000000000000000000000000001E00000000apache_exporter-1.0.0/VERSION1.0.0
07070100000010000081A4000000000000000000000001649954C000000CEE000000000000000000000000000000000000002900000000apache_exporter-1.0.0/apache_exporter.go// Copyright (c) 2015 neezgee
//
// Licensed under the MIT license: https://opensource.org/licenses/MIT
// Permission is granted to use, copy, modify, and redistribute the work.
// Full license information available in the project LICENSE file.
//

package main

import (
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/Lusitaniae/apache_exporter/collector"
	"github.com/alecthomas/kingpin/v2"
	"github.com/go-kit/log/level"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/prometheus/common/promlog"
	"github.com/prometheus/common/promlog/flag"
	"github.com/prometheus/common/version"
	"github.com/prometheus/exporter-toolkit/web"
	"github.com/prometheus/exporter-toolkit/web/kingpinflag"
)

var (
	metricsEndpoint = kingpin.Flag("telemetry.endpoint", "Path under which to expose metrics.").Default("/metrics").String()
	scrapeURI       = kingpin.Flag("scrape_uri", "URI to apache stub status page.").Default("http://localhost/server-status/?auto").String()
	hostOverride    = kingpin.Flag("host_override", "Override for HTTP Host header; empty string for no override.").Default("").String()
	insecure        = kingpin.Flag("insecure", "Ignore server certificate if using https.").Bool()
	toolkitFlags    = kingpinflag.AddFlags(kingpin.CommandLine, ":9117")
	gracefulStop    = make(chan os.Signal, 1)
	customHeaders   = kingpin.Flag("custom_headers", "Adds custom headers to the collector.").StringMap()
)

func main() {
	promlogConfig := &promlog.Config{}

	// Parse flags
	flag.AddFlags(kingpin.CommandLine, promlogConfig)
	kingpin.HelpFlag.Short('h')
	kingpin.Version(version.Print("apache_exporter"))
	kingpin.Parse()
	logger := promlog.New(promlogConfig)
	// listen to termination signals from the OS
	signal.Notify(gracefulStop, syscall.SIGTERM)
	signal.Notify(gracefulStop, syscall.SIGINT)
	signal.Notify(gracefulStop, syscall.SIGHUP)
	signal.Notify(gracefulStop, syscall.SIGQUIT)

	config := &collector.Config{
		ScrapeURI:     *scrapeURI,
		HostOverride:  *hostOverride,
		Insecure:      *insecure,
		CustomHeaders: *customHeaders,
	}

	exporter := collector.NewExporter(logger, config)
	prometheus.MustRegister(exporter)
	prometheus.MustRegister(version.NewCollector("apache_exporter"))

	level.Info(logger).Log("msg", "Starting apache_exporter", "version", version.Info())
	level.Info(logger).Log("msg", "Build context", "build", version.BuildContext())
	level.Info(logger).Log("msg", "Collect from: ", "scrape_uri", *scrapeURI)

	// listener for the termination signals from the OS
	go func() {
		level.Info(logger).Log("msg", "listening and wait for graceful stop")
		sig := <-gracefulStop
		level.Info(logger).Log("msg", "caught sig: %+v. Wait 2 seconds...", "sig", sig)
		time.Sleep(2 * time.Second)
		os.Exit(0)
	}()

	http.Handle(*metricsEndpoint, promhttp.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		_, _ = w.Write([]byte(`<html>
			 <head><title>Apache Exporter</title></head>
			 <body>
			 <h1>Apache Exporter</h1>
			 <p><a href='` + *metricsEndpoint + `'>Metrics</a></p>
			 </body>
			 </html>`))
	})

	server := &http.Server{}
	if err := web.ListenAndServe(server, toolkitFlags, logger); err != nil {
		level.Error(logger).Log("err", err)
		os.Exit(1)
	}
}
07070100000011000081A4000000000000000000000001649954C00000217D000000000000000000000000000000000000002E00000000apache_exporter-1.0.0/apache_exporter_test.go// Copyright (c) 2015 neezgee
//
// Licensed under the MIT license: https://opensource.org/licenses/MIT
// Permission is granted to use, copy, modify, and redistribute the work.
// Full license information available in the project LICENSE file.
//

package main

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/Lusitaniae/apache_exporter/collector"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/promlog"
)

const (
	apache24EventStatus = `localhost
ServerVersion: Apache/2.4.23 (Unix)
ServerMPM: event
Server Built: Jul 29 2016 04:26:14
CurrentTime: Friday, 29-Jul-2016 14:06:15 UTC
RestartTime: Friday, 29-Jul-2016 13:58:49 UTC
ParentServerConfigGeneration: 1
ParentServerMPMGeneration: 0
ServerUptimeSeconds: 445
ServerUptime: 7 minutes 25 seconds
Load1: 0.02
Load5: 0.02
Load15: 0.00
Total Accesses: 131
Total kBytes: 138
Total Duration: 12930
CPUUser: .25
CPUSystem: .15
CPUChildrenUser: 0
CPUChildrenSystem: 0
CPULoad: .0898876
Uptime: 445
ReqPerSec: .294382
BytesPerSec: 317.555
BytesPerReq: 1078.72
DurationPerReq: 98.7022
BusyWorkers: 1
IdleWorkers: 74
Processes: 5
Stopping: 0
ConnsTotal: 0
ConnsAsyncWriting: 0
ConnsAsyncKeepAlive: 0
ConnsAsyncClosing: 0
Scoreboard: _W___
`

	apache24EventTLSStatus = `localhost
ServerVersion: Apache/2.4.23 (Unix)
ServerMPM: event
Server Built: Jul 29 2016 04:26:14
CurrentTime: Friday, 29-Jul-2016 14:06:15 UTC
RestartTime: Friday, 29-Jul-2016 13:58:49 UTC
ParentServerConfigGeneration: 1
ParentServerMPMGeneration: 0
ServerUptimeSeconds: 445
ServerUptime: 7 minutes 25 seconds
Load1: 0.02
Load5: 0.02
Load15: 0.00
Total Accesses: 131
Total kBytes: 138
Total Duration: 12930
CPUUser: .25
CPUSystem: .15
CPUChildrenUser: 0
CPUChildrenSystem: 0
CPULoad: .0898876
Uptime: 445
ReqPerSec: .294382
BytesPerSec: 317.555
BytesPerReq: 1078.72
DurationPerReq: 98.7022
BusyWorkers: 1
IdleWorkers: 74
Processes: 5
Stopping: 0
ConnsTotal: 0
ConnsAsyncWriting: 0
ConnsAsyncKeepAlive: 0
ConnsAsyncClosing: 0
Scoreboard: _W___
TLSSessionCacheStatus
CacheType: SHMCB
CacheSharedMemory: 512000
CacheCurrentEntries: 0
CacheSubcaches: 32
CacheIndexesPerSubcaches: 88
CacheIndexUsage: 0%
CacheUsage: 0%
CacheStoreCount: 0
CacheReplaceCount: 0
CacheExpireCount: 0
CacheDiscardCount: 0
CacheRetrieveHitCount: 0
CacheRetrieveMissCount: 1
CacheRemoveHitCount: 0
CacheRemoveMissCount: 0
`

	apache24EventProxyStatus = `localhost
ServerVersion: Apache/2.4.23 (Unix)
ServerMPM: event
Server Built: Jul 29 2016 04:26:14
CurrentTime: Friday, 29-Jul-2016 14:06:15 UTC
RestartTime: Friday, 29-Jul-2016 13:58:49 UTC
ParentServerConfigGeneration: 1
ParentServerMPMGeneration: 0
ServerUptimeSeconds: 445
ServerUptime: 7 minutes 25 seconds
Load1: 0.02
Load5: 0.02
Load15: 0.00
Total Accesses: 131
Total kBytes: 138
Total Duration: 12930
CPUUser: .25
CPUSystem: .15
CPUChildrenUser: 0
CPUChildrenSystem: 0
CPULoad: .0898876
Uptime: 445
ReqPerSec: .294382
BytesPerSec: 317.555
BytesPerReq: 1078.72
DurationPerReq: 98.7022
BusyWorkers: 1
IdleWorkers: 74
Processes: 5
Stopping: 0
ConnsTotal: 0
ConnsAsyncWriting: 0
ConnsAsyncKeepAlive: 0
ConnsAsyncClosing: 0
Scoreboard: _W___
ProxyBalancer[0]Name: balancer://myproxy1
ProxyBalancer[0]Worker[0]Name: https://app-01:9143
ProxyBalancer[0]Worker[0]Status: Init Ok
ProxyBalancer[0]Worker[0]Elected: 5808
ProxyBalancer[0]Worker[0]Busy: 0
ProxyBalancer[0]Worker[0]Sent: 5588K
ProxyBalancer[0]Worker[0]Rcvd: 8335K
ProxyBalancer[0]Worker[1]Name: https://app-02:9143
ProxyBalancer[0]Worker[1]Status: Init Ok
ProxyBalancer[0]Worker[1]Elected: 5722
ProxyBalancer[0]Worker[1]Busy: 0
ProxyBalancer[0]Worker[1]Sent: 5167K
ProxyBalancer[0]Worker[1]Rcvd: 8267K
ProxyBalancer[0]Worker[2]Name: https://app-03:9143
ProxyBalancer[0]Worker[2]Status: Init Ok
ProxyBalancer[0]Worker[2]Elected: 5842
ProxyBalancer[0]Worker[2]Busy: 0
ProxyBalancer[0]Worker[2]Sent: 5432K
ProxyBalancer[0]Worker[2]Rcvd: 8367K
ProxyBalancer[0]Worker[3]Name: https://app-04:9143
ProxyBalancer[0]Worker[3]Status: Init Ok
ProxyBalancer[0]Worker[3]Elected: 5720
ProxyBalancer[0]Worker[3]Busy: 0
ProxyBalancer[0]Worker[3]Sent: 5576K
ProxyBalancer[0]Worker[3]Rcvd: 8175K
ProxyBalancer[1]Name: balancer://myproxy2
ProxyBalancer[1]Worker[0]Name: https://app-01:8143
ProxyBalancer[1]Worker[0]Status: Init Ok
ProxyBalancer[1]Worker[0]Elected: 5808
ProxyBalancer[1]Worker[0]Busy: 0
ProxyBalancer[1]Worker[0]Sent: 5588K
ProxyBalancer[1]Worker[0]Rcvd: 8335K
ProxyBalancer[1]Worker[1]Name: https://app-02:8143
ProxyBalancer[1]Worker[1]Status: Init Ok
ProxyBalancer[1]Worker[1]Elected: 5722
ProxyBalancer[1]Worker[1]Busy: 0
ProxyBalancer[1]Worker[1]Sent: 5167K
ProxyBalancer[1]Worker[1]Rcvd: 8267K
`

	apache24WorkerStatus = `localhost
ServerVersion: Apache/2.4.23 (Unix) OpenSSL/1.0.2h
ServerMPM: worker
Server Built: Aug 31 2016 10:54:08
CurrentTime: Thursday, 08-Sep-2016 15:09:32 CEST
RestartTime: Thursday, 08-Sep-2016 15:08:07 CEST
ParentServerConfigGeneration: 1
ParentServerMPMGeneration: 0
ServerUptimeSeconds: 85
ServerUptime: 1 minute 25 seconds
Load1: 0.00
Load5: 0.01
Load15: 0.05
Total Accesses: 10
Total kBytes: 38
Total Duration: 12930
CPUUser: .05
CPUSystem: 0
CPUChildrenUser: 0
CPUChildrenSystem: 0
CPULoad: .0588235
Uptime: 85
ReqPerSec: .117647
BytesPerSec: 457.788
BytesPerReq: 3891.2
DurationPerReq: 1293.00
BusyWorkers: 2
IdleWorkers: 48
Scoreboard: _____R_______________________K____________________....................................................................................................
`

	apache24PreforkStatus = `localhost
ServerVersion: Apache/2.4.23 (Unix) OpenSSL/1.0.2h
ServerMPM: prefork
Server Built: Aug 31 2016 10:54:08
CurrentTime: Thursday, 08-Sep-2016 15:09:32 CEST
RestartTime: Thursday, 08-Sep-2016 15:08:07 CEST
ParentServerConfigGeneration: 1
ParentServerMPMGeneration: 0
ServerUptimeSeconds: 85
ServerUptime: 1 minute 25 seconds
Load1: 0.00
Load5: 0.01
Load15: 0.05
Total Accesses: 10
Total kBytes: 38
Total Duration: 12930
CPUUser: .05
CPUSystem: 0
CPUChildrenUser: 0
CPUChildrenSystem: 0
CPULoad: .0588235
Uptime: 85
ReqPerSec: .117647
BytesPerSec: 457.788
BytesPerReq: 3891.2
DurationPerReq: 1293.00
BusyWorkers: 2
IdleWorkers: 48
Scoreboard: _____R_______________________K____________________....................................................................................................
`

	apache22Status = `Total Accesses: 302311
Total kBytes: 1677830
CPULoad: 27.4052
Uptime: 45683
ReqPerSec: 6.61758
BytesPerSec: 37609.1
BytesPerReq: 5683.21
BusyWorkers: 2
IdleWorkers: 8
Scoreboard: _W_______K......................................................................................................................................................................................................................................................
`

	metricCountApache22           = 19
	metricCountApache24Event      = 34
	metricCountApache24EventTLS   = 34
	metricCountApache24EventProxy = 64
	metricCountApache24Worker     = 28
	metricCountApache24Prefork    = 28
)

func checkApacheStatus(t *testing.T, status string, metricCount int) {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(status))
	})
	server := httptest.NewServer(handler)
	promlogConfig := &promlog.Config{}
	logger := promlog.New(promlogConfig)
	config := &collector.Config{
		ScrapeURI:     server.URL,
		HostOverride:  "",
		Insecure:      false,
		CustomHeaders: map[string]string{"Cookie": "A test cookie"},
	}
	e := collector.NewExporter(logger, config)
	ch := make(chan prometheus.Metric)

	go func() {
		defer close(ch)
		e.Collect(ch)
	}()

	for i := 1; i <= metricCount; i++ {
		m := <-ch
		if m == nil {
			t.Error("expected metric but got nil")
		}
	}
	extraMetrics := 0
	for <-ch != nil {
		extraMetrics++
	}
	if extraMetrics > 0 {
		t.Errorf("expected closed channel, got %d extra metrics", extraMetrics)
	}
}

func TestApache22Status(t *testing.T) {
	checkApacheStatus(t, apache22Status, metricCountApache22)
}

func TestApache24EventStatus(t *testing.T) {
	checkApacheStatus(t, apache24EventStatus, metricCountApache24Event)
}

func TestApache24EventTLSStatus(t *testing.T) {
	checkApacheStatus(t, apache24EventTLSStatus, metricCountApache24EventTLS)
}

func TestApache24EventProxyStatus(t *testing.T) {
	checkApacheStatus(t, apache24EventProxyStatus, metricCountApache24EventProxy)
}

func TestApache24WorkerStatus(t *testing.T) {
	checkApacheStatus(t, apache24WorkerStatus, metricCountApache24Worker)
}

func TestApache24PreforkStatus(t *testing.T) {
	checkApacheStatus(t, apache24PreforkStatus, metricCountApache24Prefork)
}
07070100000012000041ED000000000000000000000002649954C000000000000000000000000000000000000000000000002000000000apache_exporter-1.0.0/collector07070100000013000081A4000000000000000000000001649954C000003BB7000000000000000000000000000000000000002D00000000apache_exporter-1.0.0/collector/collector.go// Copyright (c) 2015 neezgee
//
// Licensed under the MIT license: https://opensource.org/licenses/MIT
// Permission is granted to use, copy, modify, and redistribute the work.
// Full license information available in the project LICENSE file.
//

package collector

import (
	"crypto/tls"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"
	"sync"

	"github.com/go-kit/log"
	"github.com/go-kit/log/level"
	"github.com/prometheus/client_golang/prometheus"
)

const (
	namespace = "apache"
)

type Exporter struct {
	URI           string
	hostOverride  string
	customHeaders map[string]string
	mutex         sync.Mutex
	client        *http.Client

	up                    *prometheus.Desc
	scrapeFailures        prometheus.Counter
	apacheVersion         *prometheus.Desc
	apacheInfo            *prometheus.GaugeVec
	generation            *prometheus.GaugeVec
	load                  *prometheus.GaugeVec
	accessesTotal         *prometheus.Desc
	kBytesTotal           *prometheus.Desc
	durationTotal         *prometheus.Desc
	cpuTotal              *prometheus.Desc
	cpuload               prometheus.Gauge
	uptime                *prometheus.Desc
	workers               *prometheus.GaugeVec
	processes             *prometheus.GaugeVec
	connections           *prometheus.GaugeVec
	scoreboard            *prometheus.GaugeVec
	proxyBalancerStatus   *prometheus.GaugeVec
	proxyBalancerElected  *prometheus.Desc
	proxyBalancerBusy     *prometheus.GaugeVec
	proxyBalancerReqSize  *prometheus.Desc
	proxyBalancerRespSize *prometheus.Desc
	logger                log.Logger
}

type Config struct {
	ScrapeURI     string
	HostOverride  string
	Insecure      bool
	CustomHeaders map[string]string
}

func NewExporter(logger log.Logger, config *Config) *Exporter {
	return &Exporter{
		URI:           config.ScrapeURI,
		hostOverride:  config.HostOverride,
		customHeaders: config.CustomHeaders,
		logger:        logger,
		up: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "up"),
			"Could the apache server be reached",
			nil,
			nil),
		scrapeFailures: prometheus.NewCounter(prometheus.CounterOpts{
			Namespace: namespace,
			Name:      "exporter_scrape_failures_total",
			Help:      "Number of errors while scraping apache.",
		}),
		apacheVersion: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "version"),
			"Apache server version",
			nil,
			nil),
		apacheInfo: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "info",
			Help:      "Apache version information",
		},
			[]string{"version", "mpm"},
		),
		generation: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "generation",
			Help:      "Apache restart generation",
		},
			[]string{"type"},
		),
		load: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "load",
			Help:      "Apache server load",
		},
			[]string{"interval"},
		),
		accessesTotal: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "accesses_total"),
			"Current total apache accesses (*)",
			nil,
			nil),
		kBytesTotal: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "sent_kilobytes_total"),
			"Current total kbytes sent (*)",
			nil,
			nil),
		durationTotal: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "duration_ms_total"),
			"Total duration of all registered requests in ms",
			nil,
			nil),
		cpuTotal: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "cpu_time_ms_total"),
			"Apache CPU time",
			[]string{"type"}, nil,
		),
		cpuload: prometheus.NewGauge(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "cpuload",
			Help:      "The current percentage CPU used by each worker and in total by all workers combined (*)",
		}),
		uptime: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "uptime_seconds_total"),
			"Current uptime in seconds (*)",
			nil,
			nil),
		workers: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "workers",
			Help:      "Apache worker statuses",
		},
			[]string{"state"},
		),
		processes: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "processes",
			Help:      "Apache process count",
		},
			[]string{"state"},
		),
		connections: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "connections",
			Help:      "Apache connection statuses",
		},
			[]string{"state"},
		),
		scoreboard: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "scoreboard",
			Help:      "Apache scoreboard statuses",
		},
			[]string{"state"},
		),
		proxyBalancerStatus: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "proxy_balancer_status",
			Help:      "Apache Proxy Balancer Statuses",
		},
			[]string{"balancer", "worker", "status"},
		),
		proxyBalancerElected: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "proxy_balancer_accesses_total"),
			"Apache Proxy Balancer Request Count",
			[]string{"balancer", "worker"}, nil,
		),
		proxyBalancerBusy: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "proxy_balancer_busy",
			Help:      "Apache Proxy Balancer Active Requests",
		},
			[]string{"balancer", "worker"},
		),
		proxyBalancerReqSize: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "proxy_balancer_request_kbytes_total"),
			"Apache Proxy Balancer Request Count",
			[]string{"balancer", "worker"}, nil,
		),
		proxyBalancerRespSize: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "proxy_balancer_response_kbytes_total"),
			"Apache Proxy Balancer Request Count",
			[]string{"balancer", "worker"}, nil,
		),
		client: &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{InsecureSkipVerify: config.Insecure},
			},
		},
	}
}

// Describe implements Prometheus.Collector.
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
	ch <- e.up
	e.scrapeFailures.Describe(ch)
	ch <- e.apacheVersion
	e.apacheInfo.Describe(ch)
	e.generation.Describe(ch)
	e.load.Describe(ch)
	ch <- e.accessesTotal
	ch <- e.kBytesTotal
	ch <- e.durationTotal
	ch <- e.cpuTotal
	e.cpuload.Describe(ch)
	ch <- e.uptime
	e.workers.Describe(ch)
	e.processes.Describe(ch)
	e.connections.Describe(ch)
	e.scoreboard.Describe(ch)
	e.proxyBalancerStatus.Describe(ch)
	ch <- e.proxyBalancerElected
	e.proxyBalancerBusy.Describe(ch)
	ch <- e.proxyBalancerReqSize
	ch <- e.proxyBalancerRespSize
}

// Split colon separated string into two fields
func splitkv(s string) (string, string) {

	if len(s) == 0 {
		return s, s
	}

	slice := strings.SplitN(s, ":", 2)

	if len(slice) == 1 {
		return slice[0], ""
	}

	return strings.TrimSpace(slice[0]), strings.TrimSpace(slice[1])
}

var scoreboardLabelMap = map[string]string{
	"_": "idle",
	"S": "startup",
	"R": "read",
	"W": "reply",
	"K": "keepalive",
	"D": "dns",
	"C": "closing",
	"L": "logging",
	"G": "graceful_stop",
	"I": "idle_cleanup",
	".": "open_slot",
}

func (e *Exporter) updateScoreboard(scoreboard string) {
	e.scoreboard.Reset()
	for _, v := range scoreboardLabelMap {
		e.scoreboard.WithLabelValues(v)
	}

	for _, worker_status := range scoreboard {
		s := string(worker_status)
		label, ok := scoreboardLabelMap[s]
		if !ok {
			label = s
		}
		e.scoreboard.WithLabelValues(label).Inc()
	}
}

func (e *Exporter) collect(ch chan<- prometheus.Metric) error {
	req, err := http.NewRequest("GET", e.URI, nil)
	if e.hostOverride != "" {
		req.Host = e.hostOverride
	}
	if err != nil {
		return fmt.Errorf("error building scraping request: %v", err)
	}
	for k, v := range e.customHeaders {
		req.Header.Add(k, v)
	}
	resp, err := e.client.Do(req)
	if err != nil {
		ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0)
		return fmt.Errorf("error scraping apache: %v", err)
	}
	ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 1)

	data, err := io.ReadAll(resp.Body)
	resp.Body.Close()
	if resp.StatusCode != 200 {
		if err != nil {
			data = []byte(err.Error())
		}
		return fmt.Errorf("status %s (%d): %s", resp.Status, resp.StatusCode, data)
	}

	lines := strings.Split(string(data), "\n")

	connectionInfo := false
	//connectionInfo := false
	version := "UNKNOWN"
	mpm := "UNKNOWN"
	balancerName := "UNKNOWN"
	workerName := "UNKNOWN"
	cpuUser := 0.0
	cpuSystem := 0.0
	cpuFound := false
	e.proxyBalancerStatus.Reset()
	e.proxyBalancerBusy.Reset()

	for _, l := range lines {
		key, v := splitkv(l)
		if err != nil {
			continue
		}

		switch {
		case key == "ServerVersion":
			var tmpstr string
			var vparts []string

			version = v
			tmpstr = strings.Split(v, "/")[1]
			tmpstr = strings.Split(tmpstr, " ")[0]
			vparts = strings.Split(tmpstr, ".")
			tmpstr = vparts[0] + "." + fmt.Sprintf("%02s", vparts[1]) + fmt.Sprintf("%03s", vparts[2])

			val, err := strconv.ParseFloat(tmpstr, 64)
			if err != nil {
				return err
			}

			ch <- prometheus.MustNewConstMetric(e.apacheVersion, prometheus.GaugeValue, val)
		case key == "ServerMPM":
			mpm = v
		case key == "ParentServerConfigGeneration":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.generation.WithLabelValues("config").Set(val)
		case key == "ParentServerMPMGeneration":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.generation.WithLabelValues("mpm").Set(val)
		case key == "Load1":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.load.WithLabelValues("1min").Set(val)
		case key == "Load5":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.load.WithLabelValues("5min").Set(val)
		case key == "Load15":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.load.WithLabelValues("15min").Set(val)
		case key == "Total Accesses":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			ch <- prometheus.MustNewConstMetric(e.accessesTotal, prometheus.CounterValue, val)
		case key == "Total kBytes":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			ch <- prometheus.MustNewConstMetric(e.kBytesTotal, prometheus.CounterValue, val)
		case key == "Total Duration":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			ch <- prometheus.MustNewConstMetric(e.durationTotal, prometheus.CounterValue, val)
		case key == "CPUUser":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			cpuUser += val
			cpuFound = true
		case key == "CPUChildrenUser":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			cpuUser += val
			cpuFound = true
		case key == "CPUSystem":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			cpuSystem += val
			cpuFound = true
		case key == "CPUChildrenSystem":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			cpuSystem += val
			cpuFound = true
		case key == "CPULoad":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.cpuload.Set(val)
		case key == "Uptime":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			ch <- prometheus.MustNewConstMetric(e.uptime, prometheus.CounterValue, val)
		case key == "BusyWorkers":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.workers.WithLabelValues("busy").Set(val)
		case key == "IdleWorkers":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.workers.WithLabelValues("idle").Set(val)
		case key == "Processes":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.processes.WithLabelValues("all").Set(val)
		case key == "Stopping":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.processes.WithLabelValues("stopping").Set(val)
		case key == "ConnsTotal":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.connections.WithLabelValues("total").Set(val)
			connectionInfo = true
		case key == "ConnsAsyncWriting":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}

			e.connections.WithLabelValues("writing").Set(val)
			connectionInfo = true
		case key == "ConnsAsyncKeepAlive":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}
			e.connections.WithLabelValues("keepalive").Set(val)
			connectionInfo = true
		case key == "ConnsAsyncClosing":
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				return err
			}
			e.connections.WithLabelValues("closing").Set(val)
			connectionInfo = true
		case key == "Scoreboard":
			e.updateScoreboard(v)
			e.scoreboard.Collect(ch)
		//ProxyBalancer[0]Name: balancer://sid2021
		//ProxyBalancer[0]Worker[0]Name: https://z-app-01:9143
		//ProxyBalancer[0]Worker[0]Status: Init Ok
		//ProxyBalancer[0]Worker[0]Elected: 5808
		//...
		case strings.HasPrefix(key, "ProxyBalancer["):
			switch {
			case strings.HasSuffix(key, "]Name"):
				if strings.Contains(key, "]Worker[") {
					workerName = v
				} else {
					balancerName = v
				}
			case strings.HasSuffix(key, "]Status"):
				e.proxyBalancerStatus.WithLabelValues(balancerName, workerName, v).Set(1)
			case strings.HasSuffix(key, "]Elected"):
				val, err := strconv.ParseFloat(v, 64)
				if err != nil {
					return err
				}
				ch <- prometheus.MustNewConstMetric(e.proxyBalancerElected, prometheus.CounterValue, val, balancerName, workerName)
			case strings.HasSuffix(key, "]Busy"):
				val, err := strconv.ParseFloat(v, 64)
				if err != nil {
					return err
				}
				e.proxyBalancerBusy.WithLabelValues(balancerName, workerName).Set(val)
			case strings.HasSuffix(key, "]Sent"):
				val, err := strconv.ParseFloat(strings.TrimRight(v, "kK"), 64)
				if err != nil {
					return err
				}
				ch <- prometheus.MustNewConstMetric(e.proxyBalancerReqSize, prometheus.CounterValue, val, balancerName, workerName)
			case strings.HasSuffix(key, "]Rcvd"):
				val, err := strconv.ParseFloat(strings.TrimRight(v, "kK"), 64)
				if err != nil {
					return err
				}
				ch <- prometheus.MustNewConstMetric(e.proxyBalancerRespSize, prometheus.CounterValue, val, balancerName, workerName)
			}
		}
	}

	if cpuFound {
		ch <- prometheus.MustNewConstMetric(e.cpuTotal, prometheus.CounterValue, 1000*cpuUser, "user")
		ch <- prometheus.MustNewConstMetric(e.cpuTotal, prometheus.CounterValue, 1000*cpuSystem, "system")
	}

	e.apacheInfo.WithLabelValues(version, mpm).Set(1)

	e.apacheInfo.Collect(ch)
	e.generation.Collect(ch)
	e.load.Collect(ch)
	e.cpuload.Collect(ch)
	e.workers.Collect(ch)
	e.processes.Collect(ch)
	if connectionInfo {
		e.connections.Collect(ch)
	}

	e.proxyBalancerStatus.Collect(ch)
	e.proxyBalancerBusy.Collect(ch)

	return nil
}

// Collect implements Prometheus.Collector.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
	e.mutex.Lock() // To protect metrics from concurrent collects.
	defer e.mutex.Unlock()
	if err := e.collect(ch); err != nil {
		level.Error(e.logger).Log("msg", "Error scraping apache:", "err", err)
		e.scrapeFailures.Inc()
		e.scrapeFailures.Collect(ch)
	}
	return
}
07070100000014000081A4000000000000000000000001649954C000000194000000000000000000000000000000000000002200000000apache_exporter-1.0.0/compose.ymlname: apache_exporter
services:
  apache_exporter:
    image: lusotycoon/apache-exporter
    container_name: apache_exporter
    privileged: true
    ports:
    - mode: ingress
      target: 9117
      published: "9117"
      protocol: tcp
    restart: unless-stopped
    extra_hosts:
    - "localhost:127.17.0.1"
    entrypoint: /bin/apache_exporter  --scrape_uri="http://172.17.0.1/server-status?auto"
07070100000015000081A4000000000000000000000001649954C000000581000000000000000000000000000000000000001D00000000apache_exporter-1.0.0/go.modmodule github.com/Lusitaniae/apache_exporter

go 1.19

require (
	github.com/alecthomas/kingpin/v2 v2.3.2
	github.com/go-kit/log v0.2.1
	github.com/prometheus/client_golang v1.15.0
	github.com/prometheus/common v0.42.0
	github.com/prometheus/exporter-toolkit v0.9.1
)

require (
	github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
	github.com/beorn7/perks v1.0.1 // indirect
	github.com/cespare/xxhash/v2 v2.2.0 // indirect
	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
	github.com/go-logfmt/logfmt v0.6.0 // indirect
	github.com/golang/protobuf v1.5.3 // indirect
	github.com/jpillora/backoff v1.0.0 // indirect
	github.com/kr/text v0.2.0 // indirect
	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
	github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
	github.com/prometheus/client_model v0.3.0 // indirect
	github.com/prometheus/procfs v0.9.0 // indirect
	github.com/rogpeppe/go-internal v1.9.0 // indirect
	github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
	golang.org/x/crypto v0.7.0 // indirect
	golang.org/x/net v0.8.0 // indirect
	golang.org/x/oauth2 v0.6.0 // indirect
	golang.org/x/sync v0.1.0 // indirect
	golang.org/x/sys v0.6.0 // indirect
	golang.org/x/text v0.8.0 // indirect
	google.golang.org/appengine v1.6.7 // indirect
	google.golang.org/protobuf v1.30.0 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
)
07070100000016000081A4000000000000000000000001649954C000001DF6000000000000000000000000000000000000001D00000000apache_exporter-1.0.0/go.sumgithub.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM=
github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/exporter-toolkit v0.9.1 h1:cNkC01riqiOS+kh3zdnNwRsbe/Blh0WwK3ij5rPJ9Sw=
github.com/prometheus/exporter-toolkit v0.9.1/go.mod h1:iFlTmFISCix0vyuyBmm0UqOUCTao9+RsAsKJP3YM9ec=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
07070100000017000041ED000000000000000000000002649954C000000000000000000000000000000000000000000000001B00000000apache_exporter-1.0.0/test07070100000018000081A4000000000000000000000001649954C0000019C7000000000000000000000000000000000000002D00000000apache_exporter-1.0.0/test/not_found.metrics# HELP apache_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, and goversion from which apache_exporter was built.
# TYPE apache_exporter_build_info gauge
apache_exporter_build_info{branch="",goversion="go1.16.4",revision="",version=""} 1
# HELP apache_exporter_scrape_failures_total Number of errors while scraping apache.
# TYPE apache_exporter_scrape_failures_total counter
apache_exporter_scrape_failures_total 1
# HELP apache_up Could the apache server be reached
# TYPE apache_up gauge
apache_up 0
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 9
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.16.4"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
go_memstats_alloc_bytes 744464
# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed.
# TYPE go_memstats_alloc_bytes_total counter
go_memstats_alloc_bytes_total 744464
# HELP go_memstats_buck_hash_sys_bytes Number of bytes used by the profiling bucket hash table.
# TYPE go_memstats_buck_hash_sys_bytes gauge
go_memstats_buck_hash_sys_bytes 4157
# HELP go_memstats_frees_total Total number of frees.
# TYPE go_memstats_frees_total counter
go_memstats_frees_total 176
# HELP go_memstats_gc_cpu_fraction The fraction of this program's available CPU time used by the GC since the program started.
# TYPE go_memstats_gc_cpu_fraction gauge
go_memstats_gc_cpu_fraction 0
# HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata.
# TYPE go_memstats_gc_sys_bytes gauge
go_memstats_gc_sys_bytes 4.017656e+06
# HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use.
# TYPE go_memstats_heap_alloc_bytes gauge
go_memstats_heap_alloc_bytes 744464
# HELP go_memstats_heap_idle_bytes Number of heap bytes waiting to be used.
# TYPE go_memstats_heap_idle_bytes gauge
go_memstats_heap_idle_bytes 6.4987136e+07
# HELP go_memstats_heap_inuse_bytes Number of heap bytes that are in use.
# TYPE go_memstats_heap_inuse_bytes gauge
go_memstats_heap_inuse_bytes 1.662976e+06
# HELP go_memstats_heap_objects Number of allocated objects.
# TYPE go_memstats_heap_objects gauge
go_memstats_heap_objects 2933
# HELP go_memstats_heap_released_bytes Number of heap bytes released to OS.
# TYPE go_memstats_heap_released_bytes gauge
go_memstats_heap_released_bytes 6.4954368e+07
# HELP go_memstats_heap_sys_bytes Number of heap bytes obtained from system.
# TYPE go_memstats_heap_sys_bytes gauge
go_memstats_heap_sys_bytes 6.6650112e+07
# HELP go_memstats_last_gc_time_seconds Number of seconds since 1970 of last garbage collection.
# TYPE go_memstats_last_gc_time_seconds gauge
go_memstats_last_gc_time_seconds 0
# HELP go_memstats_lookups_total Total number of pointer lookups.
# TYPE go_memstats_lookups_total counter
go_memstats_lookups_total 0
# HELP go_memstats_mallocs_total Total number of mallocs.
# TYPE go_memstats_mallocs_total counter
go_memstats_mallocs_total 3109
# HELP go_memstats_mcache_inuse_bytes Number of bytes in use by mcache structures.
# TYPE go_memstats_mcache_inuse_bytes gauge
go_memstats_mcache_inuse_bytes 14400
# HELP go_memstats_mcache_sys_bytes Number of bytes used for mcache structures obtained from system.
# TYPE go_memstats_mcache_sys_bytes gauge
go_memstats_mcache_sys_bytes 16384
# HELP go_memstats_mspan_inuse_bytes Number of bytes in use by mspan structures.
# TYPE go_memstats_mspan_inuse_bytes gauge
go_memstats_mspan_inuse_bytes 46648
# HELP go_memstats_mspan_sys_bytes Number of bytes used for mspan structures obtained from system.
# TYPE go_memstats_mspan_sys_bytes gauge
go_memstats_mspan_sys_bytes 49152
# HELP go_memstats_next_gc_bytes Number of heap bytes when next garbage collection will take place.
# TYPE go_memstats_next_gc_bytes gauge
go_memstats_next_gc_bytes 4.473924e+06
# HELP go_memstats_other_sys_bytes Number of bytes used for other system allocations.
# TYPE go_memstats_other_sys_bytes gauge
go_memstats_other_sys_bytes 978395
# HELP go_memstats_stack_inuse_bytes Number of bytes in use by the stack allocator.
# TYPE go_memstats_stack_inuse_bytes gauge
go_memstats_stack_inuse_bytes 458752
# HELP go_memstats_stack_sys_bytes Number of bytes obtained from system for stack allocator.
# TYPE go_memstats_stack_sys_bytes gauge
go_memstats_stack_sys_bytes 458752
# HELP go_memstats_sys_bytes Number of bytes obtained from system.
# TYPE go_memstats_sys_bytes gauge
go_memstats_sys_bytes 7.2174608e+07
# HELP go_threads Number of OS threads created.
# TYPE go_threads gauge
go_threads 9
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 0
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 1024
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 9
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 9.986048e+06
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.62290564579e+09
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 1.184079872e+09
# HELP process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes.
# TYPE process_virtual_memory_max_bytes gauge
process_virtual_memory_max_bytes -1
# HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served.
# TYPE promhttp_metric_handler_requests_in_flight gauge
promhttp_metric_handler_requests_in_flight 1
# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.
# TYPE promhttp_metric_handler_requests_total counter
promhttp_metric_handler_requests_total{code="200"} 0
promhttp_metric_handler_requests_total{code="500"} 0
promhttp_metric_handler_requests_total{code="503"} 0
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!144 blocks
openSUSE Build Service is sponsored by