summaryrefslogtreecommitdiffstats
path: root/src/go/plugin/go.d/modules/squid
diff options
context:
space:
mode:
Diffstat (limited to '')
l---------src/go/plugin/go.d/modules/squid/README.md (renamed from src/collectors/python.d.plugin/squid/README.md)0
-rw-r--r--src/go/plugin/go.d/modules/squid/charts.go81
-rw-r--r--src/go/plugin/go.d/modules/squid/collect.go105
-rw-r--r--src/go/plugin/go.d/modules/squid/config_schema.json177
-rw-r--r--src/go/plugin/go.d/modules/squid/integrations/squid.md227
-rw-r--r--src/go/plugin/go.d/modules/squid/metadata.yaml (renamed from src/collectors/python.d.plugin/squid/metadata.yaml)143
-rw-r--r--src/go/plugin/go.d/modules/squid/squid.go114
-rw-r--r--src/go/plugin/go.d/modules/squid/squid_test.go223
-rw-r--r--src/go/plugin/go.d/modules/squid/testdata/config.json20
-rw-r--r--src/go/plugin/go.d/modules/squid/testdata/config.yaml17
-rw-r--r--src/go/plugin/go.d/modules/squid/testdata/counters.txt59
l---------src/go/plugin/go.d/modules/squidlog/README.md (renamed from src/go/collectors/go.d.plugin/modules/squidlog/README.md)0
-rw-r--r--src/go/plugin/go.d/modules/squidlog/charts.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/charts.go)2
-rw-r--r--src/go/plugin/go.d/modules/squidlog/collect.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/collect.go)6
-rw-r--r--src/go/plugin/go.d/modules/squidlog/config_schema.json (renamed from src/go/collectors/go.d.plugin/modules/squidlog/config_schema.json)0
-rw-r--r--src/go/plugin/go.d/modules/squidlog/init.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/init.go)51
-rw-r--r--src/go/plugin/go.d/modules/squidlog/integrations/squid_log_files.md (renamed from src/go/collectors/go.d.plugin/modules/squidlog/integrations/squid_log_files.md)39
-rw-r--r--src/go/plugin/go.d/modules/squidlog/logline.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/logline.go)10
-rw-r--r--src/go/plugin/go.d/modules/squidlog/logline_test.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/logline_test.go)6
-rw-r--r--src/go/plugin/go.d/modules/squidlog/metadata.yaml (renamed from src/go/collectors/go.d.plugin/modules/squidlog/metadata.yaml)0
-rw-r--r--src/go/plugin/go.d/modules/squidlog/metrics.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/metrics.go)2
-rw-r--r--src/go/plugin/go.d/modules/squidlog/squidlog.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/squidlog.go)4
-rw-r--r--src/go/plugin/go.d/modules/squidlog/squidlog_test.go (renamed from src/go/collectors/go.d.plugin/modules/squidlog/squidlog_test.go)6
-rw-r--r--src/go/plugin/go.d/modules/squidlog/testdata/access.log (renamed from src/go/collectors/go.d.plugin/modules/squidlog/testdata/access.log)0
-rw-r--r--src/go/plugin/go.d/modules/squidlog/testdata/config.json (renamed from src/go/collectors/go.d.plugin/modules/squidlog/testdata/config.json)0
-rw-r--r--src/go/plugin/go.d/modules/squidlog/testdata/config.yaml (renamed from src/go/collectors/go.d.plugin/modules/squidlog/testdata/config.yaml)0
-rw-r--r--src/go/plugin/go.d/modules/squidlog/testdata/unknown.log (renamed from src/go/collectors/go.d.plugin/modules/squidlog/testdata/unknown.log)0
27 files changed, 1199 insertions, 93 deletions
diff --git a/src/collectors/python.d.plugin/squid/README.md b/src/go/plugin/go.d/modules/squid/README.md
index c4e5a03d7..c4e5a03d7 120000
--- a/src/collectors/python.d.plugin/squid/README.md
+++ b/src/go/plugin/go.d/modules/squid/README.md
diff --git a/src/go/plugin/go.d/modules/squid/charts.go b/src/go/plugin/go.d/modules/squid/charts.go
new file mode 100644
index 000000000..47bab60f4
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/charts.go
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package squid
+
+import (
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
+)
+
+const (
+ prioClientsNet = module.Priority + iota
+ prioClientsRequests
+ prioServersNet
+ prioServersRequests
+)
+
+var charts = module.Charts{
+ clientsNetChart.Copy(),
+ clientsRequestsChart.Copy(),
+ serversNetChart.Copy(),
+ serversRequestsChart.Copy(),
+}
+
+var (
+ clientsNetChart = module.Chart{
+ ID: "clients_net",
+ Title: "Squid Client Bandwidth",
+ Units: "kilobits/s",
+ Fam: "clients",
+ Ctx: "squid.clients_net",
+ Type: module.Area,
+ Priority: prioClientsNet,
+ Dims: module.Dims{
+ {ID: "client_http.kbytes_in", Name: "in", Algo: module.Incremental, Mul: 8},
+ {ID: "client_http.kbytes_out", Name: "out", Algo: module.Incremental, Mul: -8},
+ {ID: "client_http.hit_kbytes_out", Name: "hits", Algo: module.Incremental, Mul: -8},
+ },
+ }
+
+ clientsRequestsChart = module.Chart{
+ ID: "clients_requests",
+ Title: "Squid Client Requests",
+ Units: "requests/s",
+ Fam: "clients",
+ Ctx: "squid.clients_requests",
+ Type: module.Line,
+ Priority: prioClientsRequests,
+ Dims: module.Dims{
+ {ID: "client_http.requests", Name: "requests", Algo: module.Incremental},
+ {ID: "client_http.hits", Name: "hits", Algo: module.Incremental},
+ {ID: "client_http.errors", Name: "errors", Algo: module.Incremental, Mul: -1},
+ },
+ }
+
+ serversNetChart = module.Chart{
+ ID: "servers_net",
+ Title: "Squid Server Bandwidth",
+ Units: "kilobits/s",
+ Fam: "servers",
+ Ctx: "squid.servers_net",
+ Type: module.Area,
+ Priority: prioServersNet,
+ Dims: module.Dims{
+ {ID: "server.all.kbytes_in", Name: "in", Algo: module.Incremental, Mul: 8},
+ {ID: "server.all.kbytes_out", Name: "out", Algo: module.Incremental, Mul: -8},
+ },
+ }
+
+ serversRequestsChart = module.Chart{
+ ID: "servers_requests",
+ Title: "Squid Server Requests",
+ Units: "requests/s",
+ Fam: "servers",
+ Ctx: "squid.servers_requests",
+ Type: module.Line,
+ Priority: prioServersRequests,
+ Dims: module.Dims{
+ {ID: "server.all.requests", Name: "requests", Algo: module.Incremental},
+ {ID: "server.all.errors", Name: "errors", Algo: module.Incremental, Mul: -1},
+ },
+ }
+)
diff --git a/src/go/plugin/go.d/modules/squid/collect.go b/src/go/plugin/go.d/modules/squid/collect.go
new file mode 100644
index 000000000..bb0cf1ab4
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/collect.go
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package squid
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net/http"
+ "strconv"
+ "strings"
+
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
+)
+
+const (
+ // https://wiki.squid-cache.org/Features/CacheManager/Index#controlling-access-to-the-cache-manager
+ urlPathServerStats = "/squid-internal-mgr/counters"
+)
+
+var statsCounters = map[string]bool{
+ "client_http.kbytes_in": true,
+ "client_http.kbytes_out": true,
+ "server.all.errors": true,
+ "server.all.requests": true,
+ "server.all.kbytes_out": true,
+ "server.all.kbytes_in": true,
+ "client_http.errors": true,
+ "client_http.hits": true,
+ "client_http.requests": true,
+ "client_http.hit_kbytes_out": true,
+}
+
+func (s *Squid) collect() (map[string]int64, error) {
+ mx := make(map[string]int64)
+
+ if err := s.collectCounters(mx); err != nil {
+ return nil, err
+ }
+
+ return mx, nil
+}
+
+func (s *Squid) collectCounters(mx map[string]int64) error {
+ req, err := web.NewHTTPRequestWithPath(s.Request, urlPathServerStats)
+ if err != nil {
+ return err
+ }
+
+ if err := s.doOK(req, func(body io.Reader) error {
+ sc := bufio.NewScanner(body)
+
+ for sc.Scan() {
+ key, value, ok := strings.Cut(sc.Text(), "=")
+ if !ok {
+ continue
+ }
+
+ key, value = strings.TrimSpace(key), strings.TrimSpace(value)
+
+ if !statsCounters[key] {
+ continue
+ }
+
+ v, err := strconv.ParseInt(value, 10, 64)
+ if err != nil {
+ s.Debugf("failed to parse key %s value %s: %v", key, value, err)
+ continue
+ }
+
+ mx[key] = v
+ }
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ if len(mx) == 0 {
+ return fmt.Errorf("unexpected response from '%s': no metrics found", req.URL)
+ }
+
+ return nil
+}
+
+func (s *Squid) doOK(req *http.Request, parse func(body io.Reader) error) error {
+ resp, err := s.httpClient.Do(req)
+ if err != nil {
+ return fmt.Errorf("error on HTTP request '%s': %v", req.URL, err)
+ }
+
+ defer closeBody(resp)
+
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("'%s' returned HTTP status code: %d", req.URL, resp.StatusCode)
+ }
+
+ return parse(resp.Body)
+}
+
+func closeBody(resp *http.Response) {
+ if resp != nil && resp.Body != nil {
+ _, _ = io.Copy(io.Discard, resp.Body)
+ _ = resp.Body.Close()
+ }
+}
diff --git a/src/go/plugin/go.d/modules/squid/config_schema.json b/src/go/plugin/go.d/modules/squid/config_schema.json
new file mode 100644
index 000000000..b1264b2b1
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/config_schema.json
@@ -0,0 +1,177 @@
+{
+ "jsonSchema": {
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Squid collector configuration.",
+ "type": "object",
+ "properties": {
+ "update_every": {
+ "title": "Update every",
+ "description": "Data collection interval, measured in seconds.",
+ "type": "integer",
+ "minimum": 1,
+ "default": 1
+ },
+ "url": {
+ "title": "URL",
+ "description": "The base URL where the Squid endpoint can be accessed.",
+ "type": "string",
+ "default": "http://127.0.0.1:1328",
+ "format": "uri"
+ },
+ "timeout": {
+ "title": "Timeout",
+ "description": "The timeout in seconds for the HTTP request.",
+ "type": "number",
+ "minimum": 0.5,
+ "default": 1
+ },
+ "not_follow_redirects": {
+ "title": "Not follow redirects",
+ "description": "If set, the client will not follow HTTP redirects automatically.",
+ "type": "boolean"
+ },
+ "username": {
+ "title": "Username",
+ "description": "The username for basic authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "password": {
+ "title": "Password",
+ "description": "The password for basic authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "proxy_url": {
+ "title": "Proxy URL",
+ "description": "The URL of the proxy server.",
+ "type": "string"
+ },
+ "proxy_username": {
+ "title": "Proxy username",
+ "description": "The username for proxy authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "proxy_password": {
+ "title": "Proxy password",
+ "description": "The password for proxy authentication.",
+ "type": "string",
+ "sensitive": true
+ },
+ "headers": {
+ "title": "Headers",
+ "description": "Additional HTTP headers to include in the request.",
+ "type": [
+ "object",
+ "null"
+ ],
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "tls_skip_verify": {
+ "title": "Skip TLS verification",
+ "description": "If set, TLS certificate verification will be skipped.",
+ "type": "boolean"
+ },
+ "tls_ca": {
+ "title": "TLS CA",
+ "description": "The path to the CA certificate file for TLS verification.",
+ "type": "string",
+ "pattern": "^$|^/"
+ },
+ "tls_cert": {
+ "title": "TLS certificate",
+ "description": "The path to the client certificate file for TLS authentication.",
+ "type": "string",
+ "pattern": "^$|^/"
+ },
+ "tls_key": {
+ "title": "TLS key",
+ "description": "The path to the client key file for TLS authentication.",
+ "type": "string",
+ "pattern": "^$|^/"
+ },
+ "body": {
+ "title": "Body",
+ "type": "string"
+ },
+ "method": {
+ "title": "Method",
+ "type": "string"
+ }
+ },
+ "required": [
+ "url"
+ ],
+ "additionalProperties": false,
+ "patternProperties": {
+ "^name$": {}
+ }
+ },
+ "uiSchema": {
+ "uiOptions": {
+ "fullPage": true
+ },
+ "body": {
+ "ui:widget": "hidden"
+ },
+ "method": {
+ "ui:widget": "hidden"
+ },
+ "timeout": {
+ "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)."
+ },
+ "password": {
+ "ui:widget": "password"
+ },
+ "proxy_password": {
+ "ui:widget": "password"
+ },
+ "ui:flavour": "tabs",
+ "ui:options": {
+ "tabs": [
+ {
+ "title": "Base",
+ "fields": [
+ "update_every",
+ "url",
+ "timeout",
+ "not_follow_redirects"
+ ]
+ },
+ {
+ "title": "Auth",
+ "fields": [
+ "username",
+ "password"
+ ]
+ },
+ {
+ "title": "TLS",
+ "fields": [
+ "tls_skip_verify",
+ "tls_ca",
+ "tls_cert",
+ "tls_key"
+ ]
+ },
+ {
+ "title": "Proxy",
+ "fields": [
+ "proxy_url",
+ "proxy_username",
+ "proxy_password"
+ ]
+ },
+ {
+ "title": "Headers",
+ "fields": [
+ "headers"
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/src/go/plugin/go.d/modules/squid/integrations/squid.md b/src/go/plugin/go.d/modules/squid/integrations/squid.md
new file mode 100644
index 000000000..1a448de35
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/integrations/squid.md
@@ -0,0 +1,227 @@
+<!--startmeta
+custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/squid/README.md"
+meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/squid/metadata.yaml"
+sidebar_label: "Squid"
+learn_status: "Published"
+learn_rel_path: "Collecting Metrics/Web Servers and Web Proxies"
+most_popular: False
+message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE"
+endmeta-->
+
+# Squid
+
+
+<img src="https://netdata.cloud/img/squid.png" width="150"/>
+
+
+Plugin: go.d.plugin
+Module: squid
+
+<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" />
+
+## Overview
+
+This collector monitors statistics about the Squid Clients and Servers, like bandwidth and requests.
+
+
+It collects metrics from the `squid-internal-mgr/counters` endpoint.
+
+This collector is supported on all platforms.
+
+This collector supports collecting metrics from multiple instances of this integration, including remote instances.
+
+
+### Default Behavior
+
+#### Auto-Detection
+
+By default, it detects Squid instances running on localhost that are listening on port 3128.
+On startup, it tries to collect metrics from:
+
+- https://127.0.0.1:3128
+
+
+#### Limits
+
+The default configuration for this integration does not impose any limits on data collection.
+
+#### Performance Impact
+
+The default configuration for this integration is not expected to impose a significant performance impact on the system.
+
+
+## Metrics
+
+Metrics grouped by *scope*.
+
+The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels.
+
+
+
+### Per Squid instance
+
+These metrics refer to each monitored Squid instance.
+
+This scope has no labels.
+
+Metrics:
+
+| Metric | Dimensions | Unit |
+|:------|:----------|:----|
+| squid.clients_net | in, out, hits | kilobits/s |
+| squid.clients_requests | requests, hits, errors | requests/s |
+| squid.servers_net | in, out | kilobits/s |
+| squid.servers_requests | requests, errors | requests/s |
+
+
+
+## Alerts
+
+There are no alerts configured by default for this integration.
+
+
+## Setup
+
+### Prerequisites
+
+No action required.
+
+### Configuration
+
+#### File
+
+The configuration file name for this integration is `go.d/squid.conf`.
+
+
+You can edit the configuration file using the `edit-config` script from the
+Netdata [config directory](/docs/netdata-agent/configuration/README.md#the-netdata-config-directory).
+
+```bash
+cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
+sudo ./edit-config go.d/squid.conf
+```
+#### Options
+
+The following options can be defined globally: update_every, autodetection_retry.
+
+
+<details open><summary>Config options</summary>
+
+| Name | Description | Default | Required |
+|:----|:-----------|:-------|:--------:|
+| update_every | Data collection frequency. | 1 | no |
+| autodetection_retry | Recheck interval in seconds. Zero means no recheck will be scheduled. | 0 | no |
+| url | Server URL. | http://127.0.0.1:3128 | yes |
+| timeout | HTTP request timeout. | 1 | no |
+| username | Username for basic HTTP authentication. | | no |
+| password | Password for basic HTTP authentication. | | no |
+| proxy_url | Proxy URL. | | no |
+| proxy_username | Username for proxy basic HTTP authentication. | | no |
+| proxy_password | Password for proxy basic HTTP authentication. | | no |
+| method | HTTP request method. | POST | no |
+| body | HTTP request body. | | no |
+| headers | HTTP request headers. | | no |
+| not_follow_redirects | Redirect handling policy. Controls whether the client follows redirects. | no | no |
+| tls_skip_verify | Server certificate chain and hostname validation policy. Controls whether the client performs this check. | no | no |
+| tls_ca | Certification authority that the client uses when verifying the server's certificates. | | no |
+| tls_cert | Client TLS certificate. | | no |
+| tls_key | Client TLS key. | | no |
+
+</details>
+
+#### Examples
+
+##### Basic
+
+A basic example configuration.
+
+```yaml
+jobs:
+ - name: local
+ url: http://127.0.0.1:3128
+
+```
+##### Multi-instance
+
+> **Note**: When you define multiple jobs, their names must be unique.
+
+Collecting metrics from local and remote instances.
+
+
+<details open><summary>Config</summary>
+
+```yaml
+jobs:
+ - name: local
+ url: http://127.0.0.1:3128
+
+ - name: remote
+ url: http://192.0.2.1:3128
+
+```
+</details>
+
+
+
+## Troubleshooting
+
+### Debug Mode
+
+**Important**: Debug mode is not supported for data collection jobs created via the UI using the Dyncfg feature.
+
+To troubleshoot issues with the `squid` collector, run the `go.d.plugin` with the debug option enabled. The output
+should give you clues as to why the collector isn't working.
+
+- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on
+ your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`.
+
+ ```bash
+ cd /usr/libexec/netdata/plugins.d/
+ ```
+
+- Switch to the `netdata` user.
+
+ ```bash
+ sudo -u netdata -s
+ ```
+
+- Run the `go.d.plugin` to debug the collector:
+
+ ```bash
+ ./go.d.plugin -d -m squid
+ ```
+
+### Getting Logs
+
+If you're encountering problems with the `squid` collector, follow these steps to retrieve logs and identify potential issues:
+
+- **Run the command** specific to your system (systemd, non-systemd, or Docker container).
+- **Examine the output** for any warnings or error messages that might indicate issues. These messages should provide clues about the root cause of the problem.
+
+#### System with systemd
+
+Use the following command to view logs generated since the last Netdata service restart:
+
+```bash
+journalctl _SYSTEMD_INVOCATION_ID="$(systemctl show --value --property=InvocationID netdata)" --namespace=netdata --grep squid
+```
+
+#### System without systemd
+
+Locate the collector log file, typically at `/var/log/netdata/collector.log`, and use `grep` to filter for collector's name:
+
+```bash
+grep squid /var/log/netdata/collector.log
+```
+
+**Note**: This method shows logs from all restarts. Focus on the **latest entries** for troubleshooting current issues.
+
+#### Docker Container
+
+If your Netdata runs in a Docker container named "netdata" (replace if different), use this command:
+
+```bash
+docker logs netdata 2>&1 | grep squid
+```
+
+
diff --git a/src/collectors/python.d.plugin/squid/metadata.yaml b/src/go/plugin/go.d/modules/squid/metadata.yaml
index d0c5b3ecc..fbe0202ee 100644
--- a/src/collectors/python.d.plugin/squid/metadata.yaml
+++ b/src/go/plugin/go.d/modules/squid/metadata.yaml
@@ -1,11 +1,12 @@
-plugin_name: python.d.plugin
+plugin_name: go.d.plugin
modules:
- meta:
- plugin_name: python.d.plugin
+ id: collector-go.d.plugin-squid
+ plugin_name: go.d.plugin
module_name: squid
monitored_instance:
name: Squid
- link: "http://www.squid-cache.org/"
+ link: "https://www.squid-cache.org/"
categories:
- data-collection.web-servers-and-web-proxies
icon_filename: "squid.png"
@@ -23,7 +24,7 @@ modules:
data_collection:
metrics_description: |
This collector monitors statistics about the Squid Clients and Servers, like bandwidth and requests.
- method_description: "It collects metrics from the endpoint where Squid exposes its `counters` data."
+ method_description: "It collects metrics from the `squid-internal-mgr/counters` endpoint."
supported_platforms:
include: []
exclude: []
@@ -32,101 +33,121 @@ modules:
description: ""
default_behavior:
auto_detection:
- description: "By default, this collector will try to autodetect where Squid presents its `counters` data, by trying various configurations."
+ description: |
+ By default, it detects Squid instances running on localhost that are listening on port 3128.
+ On startup, it tries to collect metrics from:
+
+ - https://127.0.0.1:3128
limits:
description: ""
performance_impact:
description: ""
setup:
prerequisites:
- list:
- - title: Configure Squid's Cache Manager
- description: |
- Take a look at [Squid's official documentation](https://wiki.squid-cache.org/Features/CacheManager/Index#controlling-access-to-the-cache-manager) on how to configure access to the Cache Manager.
+ list: []
configuration:
file:
- name: "python.d/squid.conf"
+ name: "go.d/squid.conf"
options:
description: |
- There are 2 sections:
-
- * Global variables
- * One or more JOBS that can define multiple different instances to monitor.
-
- The following options can be defined globally: priority, penalty, autodetection_retry, update_every, but can also be defined per JOB to override the global values.
-
- Additionally, the following collapsed table contains all the options that can be configured inside a JOB definition.
-
- Every configuration JOB starts with a `job_name` value which will appear in the dashboard, unless a `name` parameter is specified.
+ The following options can be defined globally: update_every, autodetection_retry.
folding:
title: "Config options"
enabled: true
list:
- name: update_every
- description: Sets the default data collection frequency.
+ description: Data collection frequency.
default_value: 1
required: false
- - name: priority
- description: Controls the order of charts at the netdata dashboard.
- default_value: 60000
- required: false
- name: autodetection_retry
- description: Sets the job re-check interval in seconds.
+ description: Recheck interval in seconds. Zero means no recheck will be scheduled.
default_value: 0
required: false
- - name: penalty
- description: Indicates whether to apply penalty to update_every in case of failures.
- default_value: yes
+ - name: url
+ description: Server URL.
+ default_value: http://127.0.0.1:3128
+ required: true
+ - name: timeout
+ description: HTTP request timeout.
+ default_value: 1
required: false
- - name: name
- description: >
- Job name. This value will overwrite the `job_name` value. JOBS with the same name are mutually exclusive. Only one of them will be allowed running at any time. This allows autodetection to try several alternatives and pick the one that works.
- default_value: "local"
+ - name: username
+ description: Username for basic HTTP authentication.
+ default_value: ""
required: false
- - name: host
- description: The host to connect to.
+ - name: password
+ description: Password for basic HTTP authentication.
default_value: ""
- required: true
- - name: port
- description: The port to connect to.
+ required: false
+ - name: proxy_url
+ description: Proxy URL.
default_value: ""
- required: true
- - name: request
- description: The URL to request from Squid.
+ required: false
+ - name: proxy_username
+ description: Username for proxy basic HTTP authentication.
default_value: ""
- required: true
+ required: false
+ - name: proxy_password
+ description: Password for proxy basic HTTP authentication.
+ default_value: ""
+ required: false
+ - name: method
+ description: HTTP request method.
+ default_value: POST
+ required: false
+ - name: body
+ description: HTTP request body.
+ default_value: ""
+ required: false
+ - name: headers
+ description: HTTP request headers.
+ default_value: ""
+ required: false
+ - name: not_follow_redirects
+ description: Redirect handling policy. Controls whether the client follows redirects.
+ default_value: false
+ required: false
+ - name: tls_skip_verify
+ description: Server certificate chain and hostname validation policy. Controls whether the client performs this check.
+ default_value: false
+ required: false
+ - name: tls_ca
+ description: Certification authority that the client uses when verifying the server's certificates.
+ default_value: ""
+ required: false
+ - name: tls_cert
+ description: Client TLS certificate.
+ default_value: ""
+ required: false
+ - name: tls_key
+ description: Client TLS key.
+ default_value: ""
+ required: false
examples:
folding:
enabled: true
- title: "Config"
+ title: Config
list:
- name: Basic
- description: A basic configuration example.
+ description: A basic example configuration.
folding:
enabled: false
config: |
- example_job_name:
- name: 'local'
- host: 'localhost'
- port: 3128
- request: 'cache_object://localhost:3128/counters'
+ jobs:
+ - name: local
+ url: http://127.0.0.1:3128
- name: Multi-instance
description: |
> **Note**: When you define multiple jobs, their names must be unique.
-
+
Collecting metrics from local and remote instances.
config: |
- local_job:
- name: 'local'
- host: '127.0.0.1'
- port: 3128
- request: 'cache_object://127.0.0.1:3128/counters'
-
- remote_job:
- name: 'remote'
- host: '192.0.2.1'
- port: 3128
- request: 'cache_object://192.0.2.1:3128/counters'
+ jobs:
+ - name: local
+ url: http://127.0.0.1:3128
+
+ - name: remote
+ url: http://192.0.2.1:3128
troubleshooting:
problems:
list: []
diff --git a/src/go/plugin/go.d/modules/squid/squid.go b/src/go/plugin/go.d/modules/squid/squid.go
new file mode 100644
index 000000000..fe9c15ecb
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/squid.go
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package squid
+
+import (
+ _ "embed"
+ "errors"
+ "net/http"
+ "time"
+
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
+)
+
+//go:embed "config_schema.json"
+var configSchema string
+
+func init() {
+ module.Register("squid", module.Creator{
+ JobConfigSchema: configSchema,
+ Create: func() module.Module { return New() },
+ Config: func() any { return &Config{} },
+ })
+}
+
+func New() *Squid {
+ return &Squid{
+ Config: Config{
+ HTTP: web.HTTP{
+ Request: web.Request{
+ URL: "http://127.0.0.1:3128",
+ },
+ Client: web.Client{
+ Timeout: web.Duration(time.Second * 1),
+ },
+ },
+ },
+ charts: charts.Copy(),
+ }
+}
+
+type Config struct {
+ UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
+ web.HTTP `yaml:",inline" json:""`
+}
+
+type Squid struct {
+ module.Base
+ Config `yaml:",inline" json:""`
+
+ charts *module.Charts
+
+ httpClient *http.Client
+}
+
+func (s *Squid) Configuration() any {
+ return s.Config
+}
+
+func (s *Squid) Init() error {
+ if s.URL == "" {
+ s.Error("URL not set")
+ return errors.New("url not set")
+ }
+
+ client, err := web.NewHTTPClient(s.Client)
+ if err != nil {
+ s.Error(err)
+ return err
+ }
+ s.httpClient = client
+
+ s.Debugf("using URL %s", s.URL)
+ s.Debugf("using timeout: %s", s.Timeout)
+
+ return nil
+}
+
+func (s *Squid) Check() error {
+ mx, err := s.collect()
+ if err != nil {
+ s.Error(err)
+ return err
+ }
+
+ if len(mx) == 0 {
+ return errors.New("no metrics collected")
+ }
+
+ return nil
+}
+
+func (s *Squid) Charts() *module.Charts {
+ return s.charts
+}
+
+func (s *Squid) Collect() map[string]int64 {
+ mx, err := s.collect()
+ if err != nil {
+ s.Error(err)
+ }
+
+ if len(mx) == 0 {
+ return nil
+ }
+
+ return mx
+}
+
+func (s *Squid) Cleanup() {
+ if s.httpClient != nil {
+ s.httpClient.CloseIdleConnections()
+ }
+}
diff --git a/src/go/plugin/go.d/modules/squid/squid_test.go b/src/go/plugin/go.d/modules/squid/squid_test.go
new file mode 100644
index 000000000..c0856f89d
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/squid_test.go
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package squid
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "testing"
+
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+var (
+ dataConfigJSON, _ = os.ReadFile("testdata/config.json")
+ dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
+ dataCounters, _ = os.ReadFile("testdata/counters.txt")
+)
+
+func Test_testDataIsValid(t *testing.T) {
+ for name, data := range map[string][]byte{
+ "dataConfigJSON": dataConfigJSON,
+ "dataConfigYAML": dataConfigYAML,
+ "dataCounters": dataCounters,
+ } {
+ require.NotNil(t, data, name)
+ }
+}
+
+func TestSquid_ConfigurationSerialize(t *testing.T) {
+ module.TestConfigurationSerialize(t, &Squid{}, dataConfigJSON, dataConfigYAML)
+}
+
+func TestSquid_Init(t *testing.T) {
+ tests := map[string]struct {
+ wantFail bool
+ config Config
+ }{
+ "success with default": {
+ wantFail: false,
+ config: New().Config,
+ },
+ "fail when URL not set": {
+ wantFail: true,
+ config: Config{
+ HTTP: web.HTTP{
+ Request: web.Request{URL: ""},
+ },
+ },
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ squid := New()
+ squid.Config = test.config
+
+ if test.wantFail {
+ assert.Error(t, squid.Init())
+ } else {
+ assert.NoError(t, squid.Init())
+ }
+ })
+ }
+}
+
+func TestSquid_Charts(t *testing.T) {
+ assert.NotNil(t, New().Charts())
+}
+
+func TestSquid_Check(t *testing.T) {
+ tests := map[string]struct {
+ wantFail bool
+ prepare func(t *testing.T) (*Squid, func())
+ }{
+ "success case": {
+ wantFail: false,
+ prepare: prepareCaseSuccess,
+ },
+ "fails on unexpected response": {
+ wantFail: true,
+ prepare: prepareCaseUnexpectedResponse,
+ },
+ "fails on empty response": {
+ wantFail: true,
+ prepare: prepareCaseEmptyResponse,
+ },
+ "fails on connection refused": {
+ wantFail: true,
+ prepare: prepareCaseConnectionRefused,
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ squid, cleanup := test.prepare(t)
+ defer cleanup()
+
+ if test.wantFail {
+ assert.Error(t, squid.Check())
+ } else {
+ assert.NoError(t, squid.Check())
+ }
+ })
+ }
+}
+
+func TestSquid_Collect(t *testing.T) {
+ tests := map[string]struct {
+ prepare func(t *testing.T) (*Squid, func())
+ wantMetrics map[string]int64
+ wantCharts int
+ }{
+ "success case": {
+ prepare: prepareCaseSuccess,
+ wantCharts: len(charts),
+ wantMetrics: map[string]int64{
+ "client_http.errors": 5,
+ "client_http.hit_kbytes_out": 11,
+ "client_http.hits": 1,
+ "client_http.kbytes_in": 566,
+ "client_http.kbytes_out": 16081,
+ "client_http.requests": 9019,
+ "server.all.errors": 0,
+ "server.all.kbytes_in": 0,
+ "server.all.kbytes_out": 0,
+ "server.all.requests": 0,
+ },
+ },
+ "fails on unexpected response": {
+ prepare: prepareCaseUnexpectedResponse,
+ },
+ "fails on empty response": {
+ prepare: prepareCaseEmptyResponse,
+ },
+ "fails on connection refused": {
+ prepare: prepareCaseConnectionRefused,
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ squid, cleanup := test.prepare(t)
+ defer cleanup()
+
+ mx := squid.Collect()
+
+ require.Equal(t, test.wantMetrics, mx)
+
+ if len(test.wantMetrics) > 0 {
+ assert.Equal(t, test.wantCharts, len(*squid.Charts()))
+ module.TestMetricsHasAllChartsDims(t, squid.Charts(), mx)
+ }
+ })
+ }
+}
+
+func prepareCaseSuccess(t *testing.T) (*Squid, func()) {
+ t.Helper()
+ srv := httptest.NewServer(http.HandlerFunc(
+ func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.Path {
+ case urlPathServerStats:
+ _, _ = w.Write(dataCounters)
+ default:
+ w.WriteHeader(http.StatusNotFound)
+ }
+ }))
+
+ squid := New()
+ squid.URL = srv.URL
+ require.NoError(t, squid.Init())
+
+ return squid, srv.Close
+}
+
+func prepareCaseUnexpectedResponse(t *testing.T) (*Squid, func()) {
+ t.Helper()
+ resp := []byte(`
+Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus.
+Fusce et felis pulvinar, posuere sem non, porttitor eros.`)
+
+ srv := httptest.NewServer(http.HandlerFunc(
+ func(w http.ResponseWriter, r *http.Request) {
+ _, _ = w.Write([]byte(resp))
+ }))
+
+ squid := New()
+ squid.URL = srv.URL
+ require.NoError(t, squid.Init())
+
+ return squid, srv.Close
+}
+
+func prepareCaseEmptyResponse(t *testing.T) (*Squid, func()) {
+ t.Helper()
+ resp := []byte(``)
+
+ srv := httptest.NewServer(http.HandlerFunc(
+ func(w http.ResponseWriter, r *http.Request) {
+ _, _ = w.Write([]byte(resp))
+ }))
+
+ squid := New()
+ squid.URL = srv.URL
+ require.NoError(t, squid.Init())
+
+ return squid, srv.Close
+}
+
+func prepareCaseConnectionRefused(t *testing.T) (*Squid, func()) {
+ t.Helper()
+ squid := New()
+ squid.URL = "http://127.0.0.1:65001"
+ require.NoError(t, squid.Init())
+
+ return squid, func() {}
+}
diff --git a/src/go/plugin/go.d/modules/squid/testdata/config.json b/src/go/plugin/go.d/modules/squid/testdata/config.json
new file mode 100644
index 000000000..984c3ed6e
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/testdata/config.json
@@ -0,0 +1,20 @@
+{
+ "update_every": 123,
+ "url": "ok",
+ "body": "ok",
+ "method": "ok",
+ "headers": {
+ "ok": "ok"
+ },
+ "username": "ok",
+ "password": "ok",
+ "proxy_url": "ok",
+ "proxy_username": "ok",
+ "proxy_password": "ok",
+ "timeout": 123.123,
+ "not_follow_redirects": true,
+ "tls_ca": "ok",
+ "tls_cert": "ok",
+ "tls_key": "ok",
+ "tls_skip_verify": true
+}
diff --git a/src/go/plugin/go.d/modules/squid/testdata/config.yaml b/src/go/plugin/go.d/modules/squid/testdata/config.yaml
new file mode 100644
index 000000000..8558b61cc
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/testdata/config.yaml
@@ -0,0 +1,17 @@
+update_every: 123
+url: "ok"
+body: "ok"
+method: "ok"
+headers:
+ ok: "ok"
+username: "ok"
+password: "ok"
+proxy_url: "ok"
+proxy_username: "ok"
+proxy_password: "ok"
+timeout: 123.123
+not_follow_redirects: yes
+tls_ca: "ok"
+tls_cert: "ok"
+tls_key: "ok"
+tls_skip_verify: yes
diff --git a/src/go/plugin/go.d/modules/squid/testdata/counters.txt b/src/go/plugin/go.d/modules/squid/testdata/counters.txt
new file mode 100644
index 000000000..250a003d3
--- /dev/null
+++ b/src/go/plugin/go.d/modules/squid/testdata/counters.txt
@@ -0,0 +1,59 @@
+sample_time = 1723030944.784818 (Wed, 07 Aug 2024 11:42:24 GMT)
+client_http.requests = 9019
+client_http.hits = 1
+client_http.errors = 5
+client_http.kbytes_in = 566
+client_http.kbytes_out = 16081
+client_http.hit_kbytes_out = 11
+server.all.requests = 0
+server.all.errors = 0
+server.all.kbytes_in = 0
+server.all.kbytes_out = 0
+server.http.requests = 0
+server.http.errors = 0
+server.http.kbytes_in = 0
+server.http.kbytes_out = 0
+server.ftp.requests = 0
+server.ftp.errors = 0
+server.ftp.kbytes_in = 0
+server.ftp.kbytes_out = 0
+server.other.requests = 0
+server.other.errors = 0
+server.other.kbytes_in = 0
+server.other.kbytes_out = 0
+icp.pkts_sent = 0
+icp.pkts_recv = 0
+icp.queries_sent = 0
+icp.replies_sent = 0
+icp.queries_recv = 0
+icp.replies_recv = 0
+icp.query_timeouts = 0
+icp.replies_queued = 0
+icp.kbytes_sent = 0
+icp.kbytes_recv = 0
+icp.q_kbytes_sent = 0
+icp.r_kbytes_sent = 0
+icp.q_kbytes_recv = 0
+icp.r_kbytes_recv = 0
+icp.times_used = 0
+cd.times_used = 0
+cd.msgs_sent = 0
+cd.msgs_recv = 0
+cd.memory = 0
+cd.local_memory = 0
+cd.kbytes_sent = 0
+cd.kbytes_recv = 0
+unlink.requests = 0
+page_faults = 874
+select_loops = 91146
+cpu_time = 8.501572
+wall_time = 13.524214
+swap.outs = 0
+swap.ins = 0
+swap.files_cleaned = 0
+aborted_requests = 0
+hit_validation.attempts = 0
+hit_validation.refusals.due_to_locking = 0
+hit_validation.refusals.due_to_zeroSize = 0
+hit_validation.refusals.due_to_timeLimit = 0
+hit_validation.failures = 0
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/README.md b/src/go/plugin/go.d/modules/squidlog/README.md
index 876d4b47a..876d4b47a 120000
--- a/src/go/collectors/go.d.plugin/modules/squidlog/README.md
+++ b/src/go/plugin/go.d/modules/squidlog/README.md
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/charts.go b/src/go/plugin/go.d/modules/squidlog/charts.go
index dfac22498..92875eaf9 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/charts.go
+++ b/src/go/plugin/go.d/modules/squidlog/charts.go
@@ -5,7 +5,7 @@ package squidlog
import (
"errors"
- "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
)
type (
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/collect.go b/src/go/plugin/go.d/modules/squidlog/collect.go
index e0ebb6eb4..ee548b5be 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/collect.go
+++ b/src/go/plugin/go.d/modules/squidlog/collect.go
@@ -8,10 +8,10 @@ import (
"strconv"
"strings"
- "github.com/netdata/netdata/go/go.d.plugin/pkg/logs"
- "github.com/netdata/netdata/go/go.d.plugin/pkg/stm"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/logs"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/stm"
- "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
)
func (s *SquidLog) logPanicStackIfAny() {
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/config_schema.json b/src/go/plugin/go.d/modules/squidlog/config_schema.json
index 47e55b09b..47e55b09b 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/config_schema.json
+++ b/src/go/plugin/go.d/modules/squidlog/config_schema.json
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/init.go b/src/go/plugin/go.d/modules/squidlog/init.go
index b995b3e65..fd3a76c9a 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/init.go
+++ b/src/go/plugin/go.d/modules/squidlog/init.go
@@ -3,11 +3,10 @@
package squidlog
import (
- "bytes"
"fmt"
"strings"
- "github.com/netdata/netdata/go/go.d.plugin/pkg/logs"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/logs"
)
func (s *SquidLog) createLogReader() error {
@@ -26,28 +25,48 @@ func (s *SquidLog) createLogReader() error {
func (s *SquidLog) createParser() error {
s.Debug("starting parser creating")
- lastLine, err := logs.ReadLastLine(s.file.CurrentFilename(), 0)
- if err != nil {
- return fmt.Errorf("read last line: %v", err)
- }
- lastLine = bytes.TrimRight(lastLine, "\n")
- s.Debugf("last line: '%s'", string(lastLine))
+ const readLastLinesNum = 100
- s.parser, err = logs.NewParser(s.ParserConfig, s.file)
+ lines, err := logs.ReadLastLines(s.file.CurrentFilename(), readLastLinesNum)
if err != nil {
- return fmt.Errorf("create parser: %v", err)
+ return fmt.Errorf("failed to read last lines: %v", err)
}
- s.Debugf("created parser: %s", s.parser.Info())
- err = s.parser.Parse(lastLine, s.line)
- if err != nil {
- return fmt.Errorf("parse last line: %v (%s)", err, string(lastLine))
+ var found bool
+ for _, line := range lines {
+ if line = strings.TrimSpace(line); line == "" {
+ continue
+ }
+
+ s.Debugf("last line: '%s'", line)
+
+ s.parser, err = logs.NewParser(s.ParserConfig, s.file)
+ if err != nil {
+ s.Debugf("failed to create parser from line: %v", err)
+ continue
+ }
+
+ s.line.reset()
+
+ if err = s.parser.Parse([]byte(line), s.line); err != nil {
+ s.Debugf("failed to parse line: %v", err)
+ continue
+ }
+
+ if err = s.line.verify(); err != nil {
+ s.Debugf("failed to verify line: %v", err)
+ continue
+ }
+
+ found = true
+ break
}
- if err = s.line.verify(); err != nil {
- return fmt.Errorf("verify last line: %v (%s)", err, string(lastLine))
+ if !found {
+ return fmt.Errorf("failed to create log parser (file '%s')", s.file.CurrentFilename())
}
+
return nil
}
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/integrations/squid_log_files.md b/src/go/plugin/go.d/modules/squidlog/integrations/squid_log_files.md
index 0cf064b23..7d1e4799e 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/integrations/squid_log_files.md
+++ b/src/go/plugin/go.d/modules/squidlog/integrations/squid_log_files.md
@@ -1,6 +1,6 @@
<!--startmeta
-custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/squidlog/README.md"
-meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/squidlog/metadata.yaml"
+custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/squidlog/README.md"
+meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/squidlog/metadata.yaml"
sidebar_label: "Squid log files"
learn_status: "Published"
learn_rel_path: "Collecting Metrics/Web Servers and Web Proxies"
@@ -224,6 +224,8 @@ There are no configuration examples.
### Debug Mode
+**Important**: Debug mode is not supported for data collection jobs created via the UI using the Dyncfg feature.
+
To troubleshoot issues with the `squidlog` collector, run the `go.d.plugin` with the debug option enabled. The output
should give you clues as to why the collector isn't working.
@@ -246,4 +248,37 @@ should give you clues as to why the collector isn't working.
./go.d.plugin -d -m squidlog
```
+### Getting Logs
+
+If you're encountering problems with the `squidlog` collector, follow these steps to retrieve logs and identify potential issues:
+
+- **Run the command** specific to your system (systemd, non-systemd, or Docker container).
+- **Examine the output** for any warnings or error messages that might indicate issues. These messages should provide clues about the root cause of the problem.
+
+#### System with systemd
+
+Use the following command to view logs generated since the last Netdata service restart:
+
+```bash
+journalctl _SYSTEMD_INVOCATION_ID="$(systemctl show --value --property=InvocationID netdata)" --namespace=netdata --grep squidlog
+```
+
+#### System without systemd
+
+Locate the collector log file, typically at `/var/log/netdata/collector.log`, and use `grep` to filter for collector's name:
+
+```bash
+grep squidlog /var/log/netdata/collector.log
+```
+
+**Note**: This method shows logs from all restarts. Focus on the **latest entries** for troubleshooting current issues.
+
+#### Docker Container
+
+If your Netdata runs in a Docker container named "netdata" (replace if different), use this command:
+
+```bash
+docker logs netdata 2>&1 | grep squidlog
+```
+
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/logline.go b/src/go/plugin/go.d/modules/squidlog/logline.go
index e3d200eaf..47a8bf8f9 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/logline.go
+++ b/src/go/plugin/go.d/modules/squidlog/logline.go
@@ -245,10 +245,16 @@ func (l *logLine) assignMimeType(mime string) error {
}
// format: type/subtype, type/subtype;parameter=value
i := strings.IndexByte(mime, '/')
- if i <= 0 || !isMimeTypeValid(mime[:i]) {
+ if i <= 0 {
return fmt.Errorf("assign '%s': %w", mime, errBadMimeType)
}
+
+ if !isMimeTypeValid(mime[:i]) {
+ return nil
+ }
+
l.mimeType = mime[:i] // drop subtype
+
return nil
}
@@ -345,7 +351,7 @@ func isRespTimeValid(time int) bool {
// isCacheCodeValid does not guarantee cache result code is valid, but it is very likely.
func isCacheCodeValid(code string) bool {
// https://wiki.squid-cache.org/SquidFaq/SquidLogs#Squid_result_codes
- if code == "NONE" {
+ if code == "NONE" || code == "NONE_NONE" {
return true
}
return len(code) > 5 && (code[:4] == "TCP_" || code[:4] == "UDP_")
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/logline_test.go b/src/go/plugin/go.d/modules/squidlog/logline_test.go
index 4a9069e3f..cb3f399fe 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/logline_test.go
+++ b/src/go/plugin/go.d/modules/squidlog/logline_test.go
@@ -60,6 +60,7 @@ func TestLogLine_Assign(t *testing.T) {
{input: "UDP_MISS_NOFETCH", wantLine: logLine{cacheCode: "UDP_MISS_NOFETCH"}},
{input: "UDP_INVALID", wantLine: logLine{cacheCode: "UDP_INVALID"}},
{input: "NONE", wantLine: logLine{cacheCode: "NONE"}},
+ {input: "NONE_NONE", wantLine: logLine{cacheCode: "NONE_NONE"}},
{input: emptyStr, wantLine: emptyLogLine},
{input: hyphen, wantLine: emptyLogLine, wantErr: errBadCacheCode},
{input: "TCP", wantLine: emptyLogLine, wantErr: errBadCacheCode},
@@ -173,8 +174,8 @@ func TestLogLine_Assign(t *testing.T) {
{input: "video/3gpp", wantLine: logLine{mimeType: "video"}},
{input: emptyStr, wantLine: emptyLogLine},
{input: hyphen, wantLine: emptyLogLine},
- {input: "example/example", wantLine: emptyLogLine, wantErr: errBadMimeType},
- {input: "unknown/example", wantLine: emptyLogLine, wantErr: errBadMimeType},
+ {input: "example/example", wantLine: emptyLogLine},
+ {input: "unknown/example", wantLine: emptyLogLine},
{input: "audio", wantLine: emptyLogLine, wantErr: errBadMimeType},
{input: "/", wantLine: emptyLogLine, wantErr: errBadMimeType},
},
@@ -274,6 +275,7 @@ func TestLogLine_verify(t *testing.T) {
{input: "UDP_MISS_NOFETCH"},
{input: "UDP_INVALID"},
{input: "NONE"},
+ {input: "NONE_NONE"},
{input: emptyStr},
{input: "TCP", wantErr: errBadCacheCode},
{input: "UDP", wantErr: errBadCacheCode},
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/metadata.yaml b/src/go/plugin/go.d/modules/squidlog/metadata.yaml
index 82712f9e5..82712f9e5 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/metadata.yaml
+++ b/src/go/plugin/go.d/modules/squidlog/metadata.yaml
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/metrics.go b/src/go/plugin/go.d/modules/squidlog/metrics.go
index 3754e022b..031f832a1 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/metrics.go
+++ b/src/go/plugin/go.d/modules/squidlog/metrics.go
@@ -2,7 +2,7 @@
package squidlog
-import "github.com/netdata/netdata/go/go.d.plugin/pkg/metrics"
+import "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/metrics"
func newSummary() metrics.Summary {
return &summary{metrics.NewSummary()}
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/squidlog.go b/src/go/plugin/go.d/modules/squidlog/squidlog.go
index 6b5d36263..e2e743c69 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/squidlog.go
+++ b/src/go/plugin/go.d/modules/squidlog/squidlog.go
@@ -5,8 +5,8 @@ package squidlog
import (
_ "embed"
- "github.com/netdata/netdata/go/go.d.plugin/agent/module"
- "github.com/netdata/netdata/go/go.d.plugin/pkg/logs"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/logs"
)
//go:embed "config_schema.json"
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/squidlog_test.go b/src/go/plugin/go.d/modules/squidlog/squidlog_test.go
index 5cc8a7285..eb5ce635f 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/squidlog_test.go
+++ b/src/go/plugin/go.d/modules/squidlog/squidlog_test.go
@@ -7,10 +7,10 @@ import (
"os"
"testing"
- "github.com/netdata/netdata/go/go.d.plugin/pkg/logs"
- "github.com/netdata/netdata/go/go.d.plugin/pkg/metrics"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/logs"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/metrics"
- "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/access.log b/src/go/plugin/go.d/modules/squidlog/testdata/access.log
index 64a23d35b..64a23d35b 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/access.log
+++ b/src/go/plugin/go.d/modules/squidlog/testdata/access.log
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/config.json b/src/go/plugin/go.d/modules/squidlog/testdata/config.json
index 5d563cc7e..5d563cc7e 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/config.json
+++ b/src/go/plugin/go.d/modules/squidlog/testdata/config.json
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/config.yaml b/src/go/plugin/go.d/modules/squidlog/testdata/config.yaml
index 701205e23..701205e23 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/config.yaml
+++ b/src/go/plugin/go.d/modules/squidlog/testdata/config.yaml
diff --git a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/unknown.log b/src/go/plugin/go.d/modules/squidlog/testdata/unknown.log
index 0478a5c18..0478a5c18 100644
--- a/src/go/collectors/go.d.plugin/modules/squidlog/testdata/unknown.log
+++ b/src/go/plugin/go.d/modules/squidlog/testdata/unknown.log