Feat: QS: structure for built in integrations (#4655)

* feat: get builtin integrations started with nginx

* feat: get started with embedding and parsing of builtin integrations

* chore: add icons for nginx and redis integrations

* chore: stash current state of work

* chore: remove all yaml annotations since moved to JSON assets for bundled integrations

* chore: add file uri hydration in integration spec

* chore: refactor file uri hydration logic

* chore: add support for referencing JSON files with file uri

* chore: bring in initial integration assets

* chore: hookup builtin integrations and get all tests passing

* chore: update icons for postgres and mongo and some cleanup

* chore: some more cleanup

---------

Co-authored-by: Raj Singh <raj@Rajs-MacBook-Pro.local>
This commit is contained in:
Raj Kamal Singh 2024-03-07 19:26:20 +05:30 committed by GitHub
parent 4cd40391c5
commit a295bf2fb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 4671 additions and 2 deletions

View File

@ -0,0 +1,197 @@
package integrations
import (
"context"
"embed"
"strings"
"encoding/base64"
"encoding/json"
"fmt"
"io/fs"
"path"
koanfJson "github.com/knadh/koanf/parsers/json"
"go.signoz.io/signoz/pkg/query-service/model"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)
type BuiltInIntegrations struct{}
var builtInIntegrations map[string]IntegrationDetails
func (bi *BuiltInIntegrations) list(ctx context.Context) (
[]IntegrationDetails, *model.ApiError,
) {
integrations := maps.Values(builtInIntegrations)
slices.SortFunc(integrations, func(i1, i2 IntegrationDetails) bool {
return i1.Id < i2.Id
})
return integrations, nil
}
func (bi *BuiltInIntegrations) get(
ctx context.Context, integrationIds []string,
) (
map[string]IntegrationDetails, *model.ApiError,
) {
result := map[string]IntegrationDetails{}
for _, iid := range integrationIds {
i, exists := builtInIntegrations[iid]
if exists {
result[iid] = i
}
}
return result, nil
}
//go:embed builtin_integrations/*
var integrationFiles embed.FS
func init() {
err := readBuiltIns()
if err != nil {
panic(fmt.Errorf("couldn't read builtin integrations: %w", err))
}
}
func readBuiltIns() error {
rootDirName := "builtin_integrations"
builtinDirs, err := fs.ReadDir(integrationFiles, rootDirName)
if err != nil {
return fmt.Errorf("couldn't list integrations dirs: %w", err)
}
builtInIntegrations = map[string]IntegrationDetails{}
for _, d := range builtinDirs {
if !d.IsDir() {
continue
}
integrationDir := path.Join(rootDirName, d.Name())
i, err := readBuiltInIntegration(integrationDir)
if err != nil {
return fmt.Errorf("couldn't parse integration %s from files: %w", d.Name(), err)
}
_, exists := builtInIntegrations[i.Id]
if exists {
return fmt.Errorf(
"duplicate integration for id %s at %s", i.Id, d.Name(),
)
}
builtInIntegrations[i.Id] = *i
}
return nil
}
func readBuiltInIntegration(dirpath string) (
*IntegrationDetails, error,
) {
integrationJsonPath := path.Join(dirpath, "integration.json")
serializedSpec, err := integrationFiles.ReadFile(integrationJsonPath)
if err != nil {
return nil, fmt.Errorf("couldn't find integration.json in %s: %w", dirpath, err)
}
integrationSpec, err := koanfJson.Parser().Unmarshal(serializedSpec)
if err != nil {
return nil, fmt.Errorf(
"couldn't parse integration json from %s: %w", integrationJsonPath, err,
)
}
hydrated, err := hydrateFileUris(integrationSpec, dirpath)
if err != nil {
return nil, fmt.Errorf(
"couldn't hydrate files referenced in integration %s: %w", integrationJsonPath, err,
)
}
hydratedSpec := hydrated.(map[string]interface{})
hydratedSpecJson, err := koanfJson.Parser().Marshal(hydratedSpec)
if err != nil {
return nil, fmt.Errorf(
"couldn't serialize hydrated integration spec back to JSON %s: %w", integrationJsonPath, err,
)
}
var integration IntegrationDetails
err = json.Unmarshal(hydratedSpecJson, &integration)
if err != nil {
return nil, fmt.Errorf(
"couldn't parse hydrated JSON spec read from %s: %w",
integrationJsonPath, err,
)
}
integration.Id = "builtin::" + integration.Id
return &integration, nil
}
func hydrateFileUris(spec interface{}, basedir string) (interface{}, error) {
if specMap, ok := spec.(map[string]interface{}); ok {
result := map[string]interface{}{}
for k, v := range specMap {
hydrated, err := hydrateFileUris(v, basedir)
if err != nil {
return nil, err
}
result[k] = hydrated
}
return result, nil
} else if specSlice, ok := spec.([]interface{}); ok {
result := []interface{}{}
for _, v := range specSlice {
hydrated, err := hydrateFileUris(v, basedir)
if err != nil {
return nil, err
}
result = append(result, hydrated)
}
return result, nil
} else if maybeFileUri, ok := spec.(string); ok {
return readFileIfUri(maybeFileUri, basedir)
}
return spec, nil
}
func readFileIfUri(maybeFileUri string, basedir string) (interface{}, error) {
fileUriPrefix := "file://"
if !strings.HasPrefix(maybeFileUri, fileUriPrefix) {
return maybeFileUri, nil
}
relativePath := maybeFileUri[len(fileUriPrefix):]
fullPath := path.Join(basedir, relativePath)
fileContents, err := integrationFiles.ReadFile(fullPath)
if err != nil {
return nil, fmt.Errorf("couldn't read referenced file: %w", err)
}
if strings.HasSuffix(maybeFileUri, ".md") {
return string(fileContents), nil
} else if strings.HasSuffix(maybeFileUri, ".json") {
parsed, err := koanfJson.Parser().Unmarshal(fileContents)
if err != nil {
return nil, fmt.Errorf("couldn't parse referenced JSON file: %w", err)
}
return parsed, nil
} else if strings.HasSuffix(maybeFileUri, ".svg") {
base64Svg := base64.StdEncoding.EncodeToString(fileContents)
dataUri := fmt.Sprintf("data:image/svg+xml;base64,%s", base64Svg)
return dataUri, nil
}
return nil, fmt.Errorf("unsupported file type %s", maybeFileUri)
}

View File

@ -0,0 +1,796 @@
{
"description": "This dashboard provides a high-level overview of your MongoDB. It includes read/write performance, most-used replicas, collection metrics etc...",
"layout": [
{
"h": 3,
"i": "0c3d2b15-89be-4d62-a821-b26d93332ed3",
"moved": false,
"static": false,
"w": 6,
"x": 6,
"y": 3
},
{
"h": 3,
"i": "14504a3c-4a05-4d22-bab3-e22e94f51380",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 6
},
{
"h": 3,
"i": "dcfb3829-c3f2-44bb-907d-8dc8a6dc4aab",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 3
},
{
"h": 3,
"i": "bfc9e80b-02bf-4122-b3da-3dd943d35012",
"moved": false,
"static": false,
"w": 6,
"x": 6,
"y": 0
},
{
"h": 3,
"i": "4c07a7d2-893a-46c2-bcdb-a19b6efeac3a",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 0
},
{
"h": 3,
"i": "a5a64eec-1034-4aa6-8cb1-05673c4426c6",
"moved": false,
"static": false,
"w": 6,
"x": 6,
"y": 6
},
{
"h": 3,
"i": "503af589-ef4d-4fe3-8934-c8f7eb480d9a",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 9
}
],
"name": "",
"tags": [
"mongo",
"database"
],
"title": "Mongo overview",
"variables": {
"a2c21714-a814-4d31-9b56-7367c3208801": {
"allSelected": true,
"customValue": "",
"description": "List of hosts sending mongo metrics",
"id": "a2c21714-a814-4d31-9b56-7367c3208801",
"modificationUUID": "448e675a-4531-45b1-b434-a9ee809470d6",
"multiSelect": true,
"name": "host_name",
"order": 0,
"queryValue": "SELECT JSONExtractString(labels, 'host_name') AS host_name\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'mongodb_memory_usage'\nGROUP BY host_name",
"selectedValue": [
"Srikanths-MacBook-Pro.local"
],
"showALLOption": true,
"sort": "ASC",
"textboxValue": "",
"type": "QUERY"
}
},
"widgets": [
{
"description": "Total number of operations",
"fillSpans": false,
"id": "4c07a7d2-893a-46c2-bcdb-a19b6efeac3a",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_operation_count--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_operation_count",
"type": "Sum"
},
"aggregateOperator": "sum_rate",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "a468a30b",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "operation--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "operation",
"type": "tag"
}
],
"having": [],
"legend": "{{operation}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "7da5d899-8b06-4139-9a89-47baf9551ff8",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Operations count",
"yAxisUnit": "none"
},
{
"description": "The total time spent performing operations.",
"fillSpans": false,
"id": "bfc9e80b-02bf-4122-b3da-3dd943d35012",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_operation_time--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_operation_time",
"type": "Sum"
},
"aggregateOperator": "sum_rate",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "31be3166",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "operation--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "operation",
"type": "tag"
}
],
"having": [],
"legend": "{{operation}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "2ca35957-894a-46ae-a2a6-95d7e400d8e1",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Total operations time",
"yAxisUnit": "ms"
},
{
"description": "The number of cache operations",
"fillSpans": false,
"id": "dcfb3829-c3f2-44bb-907d-8dc8a6dc4aab",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_cache_operations--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_cache_operations",
"type": "Sum"
},
"aggregateOperator": "sum_rate",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "01b45814",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "type--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "type",
"type": "tag"
}
],
"having": [],
"legend": "{{type}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "bb439198-dcf5-4767-b0d0-ab5785159b8d",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Cache operations",
"yAxisUnit": "none"
},
{
"description": "",
"fillSpans": false,
"id": "14504a3c-4a05-4d22-bab3-e22e94f51380",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_operation_latency_time--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_operation_latency_time",
"type": "Gauge"
},
"aggregateOperator": "max",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "2e165319",
"key": {
"dataType": "string",
"id": "operation--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "operation",
"type": "tag"
},
"op": "=",
"value": "read"
},
{
"id": "888e920b",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "Latency",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "4a9cafe8-778b-476c-b825-c04e165bf285",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Read latency",
"yAxisUnit": "µs"
},
{
"description": "",
"fillSpans": false,
"id": "a5a64eec-1034-4aa6-8cb1-05673c4426c6",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_operation_latency_time--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_operation_latency_time",
"type": "Gauge"
},
"aggregateOperator": "max",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "53b37ca7",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
},
{
"id": "9862c46c",
"key": {
"dataType": "string",
"id": "operation--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "operation",
"type": "tag"
},
"op": "=",
"value": "write"
}
],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "Latency",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "446827eb-a4f2-4ff3-966b-fb65288c983b",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Write latency",
"yAxisUnit": "µs"
},
{
"description": "",
"fillSpans": false,
"id": "503af589-ef4d-4fe3-8934-c8f7eb480d9a",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_operation_latency_time--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_operation_latency_time",
"type": "Gauge"
},
"aggregateOperator": "max",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "c33ad4b6",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
},
{
"id": "c70ecfd0",
"key": {
"dataType": "string",
"id": "operation--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "operation",
"type": "tag"
},
"op": "=",
"value": "command"
}
],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "Latency",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "7b7b977d-0921-4552-8cfe-d82dfde63ef4",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Command latency",
"yAxisUnit": "µs"
},
{
"description": "",
"fillSpans": false,
"id": "0c3d2b15-89be-4d62-a821-b26d93332ed3",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_network_io_receive--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_network_io_receive",
"type": "Sum"
},
"aggregateOperator": "avg",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "5c9d7fe3",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
}
],
"having": [],
"legend": "Bytes received :: {{host_name}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
},
{
"aggregateAttribute": {
"dataType": "float64",
"id": "mongodb_network_io_transmit--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "mongodb_network_io_transmit",
"type": "Sum"
},
"aggregateOperator": "avg",
"dataSource": "metrics",
"disabled": false,
"expression": "B",
"filters": {
"items": [
{
"id": "96520885",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
}
],
"having": [],
"legend": "Bytes transmitted :: {{host_name}}",
"limit": null,
"orderBy": [],
"queryName": "B",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "41eea5bc-f9cf-45c2-92fb-ef226d6b540b",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Network IO",
"yAxisUnit": "bytes"
}
]
}

View File

@ -0,0 +1,33 @@
{
"id": "parse-default-mongo-access-log",
"name": "Parse default mongo access log",
"alias": "parse-default-mongo-access-log",
"description": "Parse standard mongo access log",
"enabled": true,
"filter": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "mongo"
}
]
},
"config": [
{
"type": "grok_parser",
"id": "parse-body-grok",
"enabled": true,
"orderId": 1,
"name": "Parse Body",
"parse_to": "attributes",
"pattern": "%{GREEDYDATA}",
"parse_from": "body"
}
]
}

View File

@ -0,0 +1,74 @@
### Configure otel collector
#### Save collector config file
Save the following collector config in a file named `mongo-collector-config.yaml`
```
receivers:
mongodb:
# - For standalone MongoDB deployments this is the hostname and port of the mongod instance
# - For replica sets specify the hostnames and ports of the mongod instances that are in the replica set configuration. If the replica_set field is specified, nodes will be autodiscovered.
# - For a sharded MongoDB deployment, please specify a list of the mongos hosts.
hosts:
- endpoint: 127.0.0.1:27017
# If authentication is required, the user can with clusterMonitor permissions can be provided here
username: monitoring
# If authentication is required, the password can be provided here.
password: ${env:MONGODB_PASSWORD}
collection_interval: 60s
# If TLS is enabled, the following fields can be used to configure the connection
tls:
insecure: true
insecure_skip_verify: true
# ca_file: /etc/ssl/certs/ca-certificates.crt
# cert_file: /etc/ssl/certs/mongodb.crt
# key_file: /etc/ssl/certs/mongodb.key
metrics:
mongodb.lock.acquire.count:
enabled: true
mongodb.lock.acquire.time:
enabled: true
mongodb.lock.acquire.wait_count:
enabled: true
mongodb.lock.deadlock.count:
enabled: true
mongodb.operation.latency.time:
enabled: true
processors:
# enriches the data with additional host information
# see https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/resourcedetectionprocessor#resource-detection-processor
resourcedetection/system:
# add additional detectors if needed
detectors: ["system"]
system:
hostname_sources: ["os"]
exporters:
# export to local collector
otlp/local:
endpoint: "localhost:4317"
tls:
insecure: true
# export to SigNoz cloud
otlp/signoz:
endpoint: "ingest.{region}.signoz.cloud:443"
tls:
insecure: false
headers:
"signoz-access-token": "<SIGNOZ_INGESTION_KEY>"
service:
pipelines:
metrics/mongodb:
receivers: [mongodb]
# note: remove this processor if the collector host is not running on the same host as the mongo instance
processors: [resourcedetection/system]
exporters: [otlp/local]
```
#### Use collector config file
Run your collector with the added flag `--config mongo-collector-config.yaml`

View File

@ -0,0 +1,22 @@
### Prepare mongo for monitoring
- Have a running mongodb instance
- Have the monitoring user created
- Have the monitoring user granted the necessary permissions
Mongodb recommends to set up a least privilege user (LPU) with a `clusterMonitor` role in order to collect.
Run the following command to create a user with the necessary permissions.
```
use admin
db.createUser(
{
user: "monitoring",
pwd: "<PASSWORD>",
roles: ["clusterMonitor"]
}
);
```
Replace `<PASSWORD>` with a strong password and set is as env var `MONGODB_PASSWORD`.

View File

@ -0,0 +1,28 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.465 22.5L11.9018 22.3132C11.9018 22.3132 11.9767 19.4633 10.9455 19.263C10.2705 18.477 11.0452 -14.2928 13.5127 19.1512C13.0446 19.3887 12.6864 19.798 12.513 20.2935C12.4201 21.0253 12.404 21.7648 12.465 22.5Z" fill="url(#paint0_linear_2128_450)"/>
<path d="M12.7695 19.7467C14.2692 18.6178 15.4177 17.0865 16.0815 15.3307C16.7453 13.5749 16.8972 11.6667 16.5195 9.828C15.417 4.96425 12.8063 3.36525 12.525 2.75475C12.2823 2.3746 12.0752 1.9729 11.9062 1.55475L12.114 15.1065C12.114 15.1065 11.6835 19.248 12.7695 19.7467Z" fill="url(#paint1_linear_2128_450)"/>
<path d="M11.6153 19.9268C11.6153 19.9268 7.0245 16.8 7.29 11.2687C7.31477 9.60123 7.6971 7.95845 8.41118 6.45136C9.12527 4.94428 10.1545 3.60799 11.4293 2.53275C11.5782 2.40618 11.6966 2.24751 11.7754 2.06864C11.8543 1.88976 11.8916 1.69535 11.8845 1.5C12.1702 2.115 12.1237 10.6823 12.1537 11.6842C12.27 15.582 11.937 19.191 11.6153 19.9268Z" fill="url(#paint2_linear_2128_450)"/>
<defs>
<linearGradient id="paint0_linear_2128_450" x1="8.67873" y1="12.1892" x2="15.1525" y2="14.3861" gradientUnits="userSpaceOnUse">
<stop offset="0.231" stop-color="#999875"/>
<stop offset="0.563" stop-color="#9B9977"/>
<stop offset="0.683" stop-color="#A09F7E"/>
<stop offset="0.768" stop-color="#A9A889"/>
<stop offset="0.837" stop-color="#B7B69A"/>
<stop offset="0.896" stop-color="#C9C7B0"/>
<stop offset="0.948" stop-color="#DEDDCB"/>
<stop offset="0.994" stop-color="#F8F6EB"/>
<stop offset="1" stop-color="#FBF9EF"/>
</linearGradient>
<linearGradient id="paint1_linear_2128_450" x1="11.0527" y1="1.45791" x2="13.9147" y2="19.3296" gradientUnits="userSpaceOnUse">
<stop stop-color="#48A547"/>
<stop offset="1" stop-color="#3F9143"/>
</linearGradient>
<linearGradient id="paint2_linear_2128_450" x1="6.8951" y1="11.8163" x2="14.5756" y2="9.24408" gradientUnits="userSpaceOnUse">
<stop stop-color="#41A247"/>
<stop offset="0.352" stop-color="#4BA74B"/>
<stop offset="0.956" stop-color="#67B554"/>
<stop offset="1" stop-color="#69B655"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,88 @@
{
"id": "mongo",
"title": "Mongo",
"description": "Monitor mongo using logs and metrics.",
"author": {
"name": "SigNoz",
"email": "integrations@signoz.io",
"homepage": "https://signoz.io"
},
"icon": "file://icon.svg",
"categories": [
"Database"
],
"overview": "file://overview.md",
"configuration": [
{
"title": "Prerequisites",
"instructions": "file://config/prerequisites.md"
},
{
"title": "Configure Otel Collector",
"instructions": "file://config/configure-otel-collector.md"
}
],
"assets": {
"logs": {
"pipelines": [
"file://assets/pipelines/log-parser.json"
]
},
"dashboards": [
"file://assets/dashboards/overview.json"
],
"alerts": []
},
"connection_tests": {
"logs": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "mongo"
}
]
}
},
"data_collected": {
"logs": [
{
"name": "Request Method",
"path": "attributes[\"http.request.method\"]",
"type": "string",
"description": "HTTP method"
},
{
"name": "Request Path",
"path": "attributes[\"url.path\"]",
"type": "string",
"description": "path requested"
},
{
"name": "Response Status Code",
"path": "attributes[\"http.response.status_code\"]",
"type": "int",
"description": "HTTP response code"
}
],
"metrics": [
{
"name": "http.server.request.duration",
"type": "Histogram",
"unit": "s",
"description": "Duration of HTTP server requests"
},
{
"name": "http.server.active_requests",
"type": "UpDownCounter",
"unit": "{ request }",
"description": "Number of active HTTP server requests"
}
]
}
}

View File

@ -0,0 +1,3 @@
### Monitor MongoDB with SigNoz
Collect key MongoDB metrics and parse your MongoDB logs

View File

@ -0,0 +1,62 @@
{
"id": "parse-default-nginx-access-log",
"name": "Parse default nginx access log",
"alias": "parse-default-nginx-access-log",
"description": "Parse standard nginx access log",
"enabled": true,
"filter": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "nginx"
}
]
},
"config": [
{
"type": "grok_parser",
"id": "parse-body-grok",
"enabled": true,
"orderId": 1,
"name": "Parse Body",
"parse_to": "attributes",
"pattern": "%{IP:client.address} - %{USERNAME:enduser.id} \\[%{HTTPDATE:time.local}\\] \"((%{WORD:http.method} %{DATA:http.path}(\\?%{DATA:http.query})? %{WORD:network.protocol.name}/%{NOTSPACE:network.protocol.version})|%{DATA})\" %{INT:http.response.status_code:int} %{INT:http.request.body.bytes:int} \"%{NOTSPACE:http.referer}\" \"%{DATA:http.user.agent}\" %{INT:http.request.bytes:int} %{NUMBER:http.request.time:float} \\[%{DATA:proxy.upstream.name}?\\] \\[%{DATA:proxy.alternative.upstream.name}?\\] ((%{IP:network.peer.address}:%{INT:network.peer.port:int})|%{DATA})? (%{INT:http.response.bytes:int}|-)? (%{NUMBER:http.response.time:float}|-)? (%{NUMBER:network.peer.status.code:int}|-)? %{NOTSPACE:request.id}",
"parse_from": "body"
},
{
"type": "severity_parser",
"id": "parse-sev",
"enabled": true,
"orderId": 2,
"name": "Set Severity",
"parse_from": "attributes[\"http.response.status_code\"]",
"mapping": {
"debug": [
"1xx"
],
"error": [
"4xx"
],
"fatal": [
"5xx"
],
"info": [
"2xx"
],
"trace": [
"trace"
],
"warn": [
"3xx"
]
},
"overwrite_text": true
}
]
}

View File

@ -0,0 +1 @@
### Configure otel collector

View File

@ -0,0 +1 @@
### Prepare nginx for observability

View File

@ -0,0 +1,8 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M11.961 1.5H12.0098C12.2596 1.619 12.5029 1.75118 12.7388 1.896C15.4532 3.457 18.1678 5.0185 20.8823 6.5805C20.9873 6.63656 21.073 6.72287 21.1284 6.82825C21.1837 6.93363 21.2062 7.05322 21.1927 7.1715C21.1867 10.4633 21.1927 13.7542 21.189 17.0445C21.1537 17.2015 21.0577 17.3382 20.922 17.4247C18.0355 19.0868 15.1488 20.7478 12.2618 22.4078C12.1918 22.4611 12.1075 22.4922 12.0196 22.4972C11.9318 22.5021 11.8445 22.4806 11.769 22.4355C8.879 20.7785 5.99175 19.1185 3.10725 17.4555C3.0135 17.4112 2.93499 17.3401 2.8816 17.2512C2.82821 17.1623 2.80234 17.0596 2.80725 16.956C2.80725 13.665 2.80725 10.3742 2.80725 7.08375C2.80018 6.98062 2.82401 6.87773 2.87572 6.78822C2.92742 6.69871 3.00464 6.62665 3.0975 6.58125C5.8085 5.02225 8.5195 3.46225 11.2305 1.90125C11.472 1.76325 11.709 1.617 11.961 1.5Z"
fill="#019639" />
<path
d="M6.57525 7.9035C6.57525 10.618 6.57525 13.3327 6.57525 16.0477C6.57179 16.1981 6.59832 16.3476 6.65331 16.4876C6.7083 16.6276 6.79063 16.7552 6.8955 16.863C7.09652 17.0616 7.35953 17.1852 7.64069 17.2133C7.92185 17.2415 8.20414 17.1723 8.4405 17.0175C8.59871 16.91 8.72823 16.7654 8.81778 16.5964C8.90732 16.4274 8.95417 16.239 8.95425 16.0477C8.95425 14.0827 8.9505 12.1177 8.95425 10.1527C10.7457 12.2977 12.541 14.4397 14.34 16.5787C14.5899 16.832 14.8995 17.0183 15.2402 17.1208C15.5809 17.2233 15.9419 17.2386 16.29 17.1652C16.5358 17.1168 16.7596 16.9908 16.9285 16.8057C17.0974 16.6206 17.2025 16.3862 17.2283 16.137C17.2323 13.3665 17.2323 10.5962 17.2283 7.82625C17.2024 7.53057 17.0667 7.2553 16.8479 7.05477C16.6291 6.85423 16.3431 6.74299 16.0462 6.74299C15.7494 6.74299 15.4634 6.85423 15.2446 7.05477C15.0258 7.2553 14.8901 7.53057 14.8643 7.82625C14.8643 9.82275 14.8523 11.817 14.8643 13.8127C13.1048 11.7382 11.367 9.64575 9.61425 7.56375C9.38317 7.26744 9.07725 7.03813 8.72803 6.89944C8.3788 6.76075 7.9989 6.71771 7.6275 6.77475C7.34615 6.80607 7.08532 6.93714 6.89229 7.14421C6.69925 7.35128 6.58678 7.62064 6.57525 7.9035Z"
fill="white" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,87 @@
{
"id": "nginx",
"title": "Nginx",
"description": "Monitor nginx using logs and metrics.",
"author": {
"name": "SigNoz",
"email": "integrations@signoz.io",
"homepage": "https://signoz.io"
},
"icon": "file://icon.svg",
"categories": [
"Ingress",
"HTTP"
],
"overview": "file://overview.md",
"configuration": [
{
"title": "Prepare Nginx",
"instructions": "file://config/prepare-nginx.md"
},
{
"title": "Configure Otel Collector",
"instructions": "file://config/configure-otel-collector.md"
}
],
"assets": {
"logs": {
"pipelines": [
"file://assets/pipelines/log-parser.json"
]
},
"dashboards": null,
"alerts": null
},
"connection_tests": {
"logs": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "nginx"
}
]
}
},
"data_collected": {
"logs": [
{
"name": "Request Method",
"path": "attributes[\"http.request.method\"]",
"type": "string",
"description": "HTTP method"
},
{
"name": "Request Path",
"path": "attributes[\"url.path\"]",
"type": "string",
"description": "path requested"
},
{
"name": "Response Status Code",
"path": "attributes[\"http.response.status_code\"]",
"type": "int",
"description": "HTTP response code"
}
],
"metrics": [
{
"name": "http.server.request.duration",
"type": "Histogram",
"unit": "s",
"description": "Duration of HTTP server requests"
},
{
"name": "http.server.active_requests",
"type": "UpDownCounter",
"unit": "{ request }",
"description": "Number of active HTTP server requests"
}
]
}
}

View File

@ -0,0 +1,3 @@
### Monitor Nginx with SigNoz
Parse your Nginx logs and collect key metrics.

View File

@ -0,0 +1,33 @@
{
"id": "parse-default-postgres-access-log",
"name": "Parse default postgres access log",
"alias": "parse-default-postgres-access-log",
"description": "Parse standard postgres access log",
"enabled": true,
"filter": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "postgres"
}
]
},
"config": [
{
"type": "grok_parser",
"id": "parse-body-grok",
"enabled": true,
"orderId": 1,
"name": "Parse Body",
"parse_to": "attributes",
"pattern": "%{GREEDYDATA}",
"parse_from": "body"
}
]
}

View File

@ -0,0 +1,72 @@
### Configure otel collector
#### Save collector config file
Save the following collector config in a file named `postgres-collector-config.yaml`
```
receivers:
postgresql:
# The endpoint of the postgresql server. Whether using TCP or Unix sockets, this value should be host:port. If transport is set to unix, the endpoint will internally be translated from host:port to /host.s.PGSQL.port
endpoint: "localhost:5432"
# The frequency at which to collect metrics from the Postgres instance.
collection_interval: 60s
# The username used to access the postgres instance
username: monitoring
# The password used to access the postgres instance
password: ${env:POSTGRESQL_PASSWORD}
# The list of databases for which the receiver will attempt to collect statistics. If an empty list is provided, the receiver will attempt to collect statistics for all non-template databases
databases: []
# List of databases which will be excluded when collecting statistics.
exclude_databases: []
# # Defines the network to use for connecting to the server. Valid Values are `tcp` or `unix`
# transport: tcp
tls:
# set to false if SSL is enabled on the server
insecure: true
# ca_file: /etc/ssl/certs/ca-certificates.crt
# cert_file: /etc/ssl/certs/postgres.crt
# key_file: /etc/ssl/certs/postgres.key
metrics:
postgresql.database.locks:
enabled: true
postgresql.deadlocks:
enabled: true
postgresql.sequential_scans:
enabled: true
processors:
# enriches the data with additional host information
# see https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/resourcedetectionprocessor#resource-detection-processor
resourcedetection/system:
# add additional detectors if needed
detectors: ["system"]
system:
hostname_sources: ["os"]
exporters:
# export to local collector
otlp/local:
endpoint: "localhost:4317"
tls:
insecure: true
# export to SigNoz cloud
otlp/signoz:
endpoint: "ingest.{region}.signoz.cloud:443"
tls:
insecure: false
headers:
"signoz-access-token": "<SIGNOZ_INGESTION_KEY>"
service:
pipelines:
metrics/postgresql:
receivers: [postgresql]
# note: remove this processor if the collector host is not running on the same host as the postgres instance
processors: [resourcedetection/system]
exporters: [otlp/local]
```
#### Use collector config file
Run your collector with the added flag `--config postgres-collector-config.yaml`

View File

@ -0,0 +1,26 @@
### Prepare postgres for monitoring
- Have a running postgresql instance
- Have the monitoring user created
- Have the monitoring user granted the necessary permissions
This receiver supports PostgreSQL versions 9.6+
For PostgreSQL versions 10+, run:
```
create user monitoring with password '<PASSWORD>';
grant pg_monitor to monitoring;
grant SELECT ON pg_stat_database to monitoring;
```
For PostgreSQL versions >= 9.6 and <10, run:
```
create user monitoring with password '<PASSWORD>';
grant SELECT ON pg_stat_database to monitoring;
```
Set the following environment variables:
- POSTGRESQL_PASSWORD

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1,88 @@
{
"id": "postgres",
"title": "PostgreSQL",
"description": "Monitor postgres using logs and metrics.",
"author": {
"name": "SigNoz",
"email": "integrations@signoz.io",
"homepage": "https://signoz.io"
},
"icon": "file://icon.svg",
"categories": [
"Database"
],
"overview": "file://overview.md",
"configuration": [
{
"title": "Prerequisites",
"instructions": "file://config/prerequisites.md"
},
{
"title": "Configure Otel Collector",
"instructions": "file://config/configure-otel-collector.md"
}
],
"assets": {
"logs": {
"pipelines": [
"file://assets/pipelines/log-parser.json"
]
},
"dashboards": [
"file://assets/dashboards/overview.json"
],
"alerts": []
},
"connection_tests": {
"logs": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "postgres"
}
]
}
},
"data_collected": {
"logs": [
{
"name": "Request Method",
"path": "attributes[\"http.request.method\"]",
"type": "string",
"description": "HTTP method"
},
{
"name": "Request Path",
"path": "attributes[\"url.path\"]",
"type": "string",
"description": "path requested"
},
{
"name": "Response Status Code",
"path": "attributes[\"http.response.status_code\"]",
"type": "int",
"description": "HTTP response code"
}
],
"metrics": [
{
"name": "http.server.request.duration",
"type": "Histogram",
"unit": "s",
"description": "Duration of HTTP server requests"
},
{
"name": "http.server.active_requests",
"type": "UpDownCounter",
"unit": "{ request }",
"description": "Number of active HTTP server requests"
}
]
}
}

View File

@ -0,0 +1,3 @@
### Monitor Postgres with SigNoz
Parse your Postgres logs and collect key metrics.

View File

@ -0,0 +1,923 @@
{
"description": "This dashboard shows the Redis instance overview. It includes latency, hit/miss rate, connections, and memory information.\n",
"layout": [
{
"h": 3,
"i": "d4c164bc-8fc2-4dbc-aadd-8d17479ca649",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 9
},
{
"h": 3,
"i": "2fbaef0d-3cdb-4ce3-aa3c-9bbbb41786d9",
"moved": false,
"static": false,
"w": 6,
"x": 3,
"y": 6
},
{
"h": 3,
"i": "f5ee1511-0d2b-4404-9ce0-e991837decc2",
"moved": false,
"static": false,
"w": 6,
"x": 6,
"y": 3
},
{
"h": 3,
"i": "b19c7058-b806-4ea2-974a-ca555b168991",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 3
},
{
"h": 3,
"i": "bf0deeeb-e926-4234-944c-82bacd96af47",
"moved": false,
"static": false,
"w": 6,
"x": 6,
"y": 0
},
{
"h": 3,
"i": "a77227c7-16f5-4353-952e-b183c715a61c",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 0
},
{
"h": 3,
"i": "9698cee2-b1f3-4c0b-8c9f-3da4f0e05f17",
"moved": false,
"static": false,
"w": 6,
"x": 6,
"y": 9
},
{
"h": 3,
"i": "64a5f303-d7db-44ff-9a0e-948e5c653320",
"moved": false,
"static": false,
"w": 6,
"x": 0,
"y": 12
},
{
"h": 3,
"i": "3e80a918-69af-4c9a-bc57-a94e1d41b05c",
"moved": false,
"static": false,
"w": 6,
"x": 6,
"y": 12
}
],
"name": "",
"tags": [
"redis",
"database"
],
"title": "Redis overview",
"variables": {
"94f19b3c-ad9f-4b47-a9b2-f312c09fa965": {
"allSelected": true,
"customValue": "",
"description": "List of hosts sending Redis metrics",
"id": "94f19b3c-ad9f-4b47-a9b2-f312c09fa965",
"key": "94f19b3c-ad9f-4b47-a9b2-f312c09fa965",
"modificationUUID": "4c5b0c03-9cbc-425b-8d8e-7152e5c39ba8",
"multiSelect": true,
"name": "host_name",
"order": 0,
"queryValue": "SELECT JSONExtractString(labels, 'host_name') AS host_name\nFROM signoz_metrics.distributed_time_series_v4_1day\nWHERE metric_name = 'redis_cpu_time'\nGROUP BY host_name",
"selectedValue": [
"Srikanths-MacBook-Pro.local"
],
"showALLOption": true,
"sort": "ASC",
"textboxValue": "",
"type": "QUERY"
}
},
"widgets": [
{
"description": "Rate successful lookup of keys in the main dictionary",
"fillSpans": false,
"id": "a77227c7-16f5-4353-952e-b183c715a61c",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_keyspace_hits--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "redis_keyspace_hits",
"type": "Sum"
},
"aggregateOperator": "sum_rate",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "e99669ea",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "Hit/s across all hosts",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "42c9c117-bfaf-49f7-b528-aad099392295",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Hits/s",
"yAxisUnit": "none"
},
{
"description": "Number of clients pending on a blocking call",
"fillSpans": false,
"id": "bf0deeeb-e926-4234-944c-82bacd96af47",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_clients_blocked--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "redis_clients_blocked",
"type": "Sum"
},
"aggregateOperator": "sum",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "97247f25",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "Blocked clients across all hosts",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "b77a9e11-fb98-4a95-88a8-c3ad25c14369",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Clients blocked",
"yAxisUnit": "none"
},
{
"description": "",
"fillSpans": false,
"id": "b19c7058-b806-4ea2-974a-ca555b168991",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "",
"id": "redis_db_keys------false",
"isColumn": false,
"key": "redis_db_keys",
"type": ""
},
"aggregateOperator": "sum",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "b77a9e11-fb98-4a95-88a8-c3ad25c14369",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Keyspace Keys",
"yAxisUnit": "none"
},
{
"description": "Number of changes since the last dump",
"fillSpans": false,
"id": "f5ee1511-0d2b-4404-9ce0-e991837decc2",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_rdb_changes_since_last_save--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "redis_rdb_changes_since_last_save",
"type": "Sum"
},
"aggregateOperator": "sum",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "d4aef346",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "Number of unsaved changes",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "32cedddf-606d-4de1-8c1d-4b7049e6430c",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Unsaved changes",
"yAxisUnit": "none"
},
{
"description": "",
"fillSpans": false,
"id": "2fbaef0d-3cdb-4ce3-aa3c-9bbbb41786d9",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_commands--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "redis_commands",
"type": "Gauge"
},
"aggregateOperator": "sum",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "458dc402",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [],
"having": [],
"legend": "ops/s",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "c70de4dd-a68a-42df-a249-6610c296709c",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Command/s",
"yAxisUnit": "ops"
},
{
"description": "",
"fillSpans": false,
"id": "d4c164bc-8fc2-4dbc-aadd-8d17479ca649",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_memory_used--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "redis_memory_used",
"type": "Gauge"
},
"aggregateOperator": "sum",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "394a537e",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
}
],
"having": [],
"legend": "Used::{{host_name}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
},
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_maxmemory--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "redis_maxmemory",
"type": "Gauge"
},
"aggregateOperator": "max",
"dataSource": "metrics",
"disabled": false,
"expression": "B",
"filters": {
"items": [
{
"id": "0c0754da",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
}
],
"having": [],
"legend": "Max::{{host_name}}",
"limit": null,
"orderBy": [],
"queryName": "B",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "2f47df76-f09e-4152-8623-971f0fe66bfe",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Memory usage",
"yAxisUnit": "bytes"
},
{
"description": "",
"fillSpans": false,
"id": "9698cee2-b1f3-4c0b-8c9f-3da4f0e05f17",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_memory_rss--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "redis_memory_rss",
"type": "Gauge"
},
"aggregateOperator": "sum",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "4dc9ae49",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
}
],
"having": [],
"legend": "Rss::{{host_name}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "fddd043c-1385-481c-9f4c-381f261e1dd9",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "RSS Memory",
"yAxisUnit": "bytes"
},
{
"description": "",
"fillSpans": false,
"id": "64a5f303-d7db-44ff-9a0e-948e5c653320",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_memory_fragmentation_ratio--float64--Gauge--true",
"isColumn": true,
"isJSON": false,
"key": "redis_memory_fragmentation_ratio",
"type": "Gauge"
},
"aggregateOperator": "avg",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "79dc25f3",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
}
],
"having": [],
"legend": "Rss::{{host_name}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "3e802b07-0249-4d79-a5c7-6580ab535ad0",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Fragmentation ratio",
"yAxisUnit": "short"
},
{
"description": "Number of evicted keys due to maxmemory limit",
"fillSpans": false,
"id": "3e80a918-69af-4c9a-bc57-a94e1d41b05c",
"isStacked": false,
"nullZeroValues": "zero",
"opacity": "1",
"panelTypes": "graph",
"query": {
"builder": {
"queryData": [
{
"aggregateAttribute": {
"dataType": "float64",
"id": "redis_keys_evicted--float64--Sum--true",
"isColumn": true,
"isJSON": false,
"key": "redis_keys_evicted",
"type": "Sum"
},
"aggregateOperator": "sum_rate",
"dataSource": "metrics",
"disabled": false,
"expression": "A",
"filters": {
"items": [
{
"id": "53d189ac",
"key": {
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
},
"op": "in",
"value": [
"{{.host_name}}"
]
}
],
"op": "AND"
},
"groupBy": [
{
"dataType": "string",
"id": "host_name--string--tag--false",
"isColumn": false,
"isJSON": false,
"key": "host_name",
"type": "tag"
}
],
"having": [],
"legend": "Rss::{{host_name}}",
"limit": null,
"orderBy": [],
"queryName": "A",
"reduceTo": "sum",
"stepInterval": 60
}
],
"queryFormulas": []
},
"clickhouse_sql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"id": "15d1d9d7-eb10-464b-aa7b-33ff211996f7",
"promql": [
{
"disabled": false,
"legend": "",
"name": "A",
"query": ""
}
],
"queryType": "builder"
},
"softMax": null,
"softMin": null,
"thresholds": [],
"timePreferance": "GLOBAL_TIME",
"title": "Eviction rate",
"yAxisUnit": "short"
}
]
}

View File

@ -0,0 +1,33 @@
{
"id": "parse-default-redis-access-log",
"name": "Parse default redis access log",
"alias": "parse-default-redis-access-log",
"description": "Parse standard redis access log",
"enabled": true,
"filter": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "redis"
}
]
},
"config": [
{
"type": "grok_parser",
"id": "parse-body-grok",
"enabled": true,
"orderId": 1,
"name": "Parse Body",
"parse_to": "attributes",
"pattern": "%{GREEDYDATA}",
"parse_from": "body"
}
]
}

View File

@ -0,0 +1,63 @@
### Configure otel collector
#### Save collector config file
Save the following collector config in a file named `redis-collector-config.yaml`
```
receivers:
redis:
# The hostname and port of the Redis instance, separated by a colon.
endpoint: "localhost:6379"
# The frequency at which to collect metrics from the Redis instance.
collection_interval: 60s
# # The password used to access the Redis instance; must match the password specified in the requirepass server configuration option.
# password: ${env:REDIS_PASSWORD}
# # Defines the network to use for connecting to the server. Valid Values are `tcp` or `Unix`
# transport: tcp
# tls:
# insecure: false
# ca_file: /etc/ssl/certs/ca-certificates.crt
# cert_file: /etc/ssl/certs/redis.crt
# key_file: /etc/ssl/certs/redis.key
metrics:
redis.maxmemory:
enabled: true
redis.cmd.latency:
enabled: true
processors:
# enriches the data with additional host information
# see https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/resourcedetectionprocessor#resource-detection-processor
resourcedetection/system:
# add additional detectors if needed
detectors: ["system"]
system:
hostname_sources: ["os"]
exporters:
# export to local collector
otlp/local:
endpoint: "localhost:4317"
tls:
insecure: true
# export to SigNoz cloud
otlp/signoz:
endpoint: "ingest.{region}.signoz.cloud:443"
tls:
insecure: false
headers:
"signoz-access-token": "<SIGNOZ_INGESTION_KEY>"
service:
pipelines:
metrics/redis:
receivers: [redis]
# note: remove this processor if the collector host is not running on the same host as the redis instance
processors: [resourcedetection/system]
exporters: [otlp/local]
```
#### Use collector config file
Run your collector with the added flag `--config redis-collector-config.yaml`

View File

@ -0,0 +1,5 @@
### Prepare redis for monitoring
- Have a running redis instance
- Have the monitoring user created
- Have the monitoring user granted the necessary permissions

View File

@ -0,0 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.0597 17.5259C21.7789 18.1935 15.144 20.9215 13.7315 21.6579C12.3189 22.3944 11.5343 22.3873 10.4183 21.8539C9.30253 21.3204 2.24184 18.4684 0.969937 17.8604C0.334312 17.5567 0 17.3002 0 17.0579V14.632C0 14.632 9.19219 12.6309 10.6762 12.0985C12.16 11.5661 12.6749 11.5469 13.9377 12.0095C15.2007 12.4722 22.7519 13.8346 24 14.2917L23.9994 16.6833C23.9996 16.9231 23.7116 17.1862 23.0597 17.5259Z" fill="#912626"/>
<path d="M23.0592 15.1144C21.7785 15.7817 15.1438 18.5098 13.7313 19.2461C12.3188 19.9827 11.5342 19.9755 10.4183 19.4421C9.30244 18.909 2.24203 16.0565 0.970219 15.4489C-0.301594 14.8409 -0.328219 14.4225 0.921094 13.9333C2.17041 13.4439 9.19209 10.6891 10.6763 10.1567C12.1601 9.62447 12.6749 9.60506 13.9377 10.0678C15.2006 10.5304 21.7958 13.1555 23.0437 13.6125C24.292 14.0701 24.3399 14.4469 23.0592 15.1144Z" fill="#C6302B"/>
<path d="M23.0597 13.6007C21.7789 14.2684 15.144 16.9963 13.7315 17.733C12.3189 18.4692 11.5343 18.4621 10.4183 17.9287C9.30244 17.3955 2.24184 14.5432 0.969937 13.9352C0.334312 13.6314 0 13.3753 0 13.133V10.7068C0 10.7068 9.19219 8.70581 10.6762 8.1734C12.16 7.641 12.6749 7.62168 13.9377 8.08434C15.2008 8.547 22.752 9.90909 24 10.3663L23.9994 12.7582C23.9996 12.9979 23.7116 13.2609 23.0597 13.6007Z" fill="#912626"/>
<path d="M23.0592 11.1892C21.7785 11.8567 15.1438 14.5846 13.7313 15.3212C12.3188 16.0575 11.5342 16.0503 10.4183 15.5168C9.30244 14.9838 2.24203 12.1313 0.970219 11.5237C-0.301594 10.9159 -0.328219 10.4974 0.921094 10.008C2.17041 9.51891 9.19219 6.76387 10.6763 6.23156C12.1601 5.69925 12.6749 5.67994 13.9377 6.14259C15.2006 6.60516 21.7958 9.23006 23.0437 9.68728C24.292 10.1448 24.3399 10.5217 23.0592 11.1892Z" fill="#C6302B"/>
<path d="M23.0597 9.52997C21.7789 10.1975 15.144 12.9256 13.7315 13.6623C12.3189 14.3986 11.5343 14.3914 10.4183 13.8579C9.30244 13.3248 2.24184 10.4723 0.969937 9.86465C0.334312 9.56062 0 9.3044 0 9.06234V6.63609C0 6.63609 9.19219 4.63519 10.6762 4.10287C12.16 3.57037 12.6749 3.55125 13.9377 4.01381C15.2008 4.47647 22.752 5.83856 24 6.29578L23.9994 8.68753C23.9996 8.92706 23.7116 9.19012 23.0597 9.52997Z" fill="#912626"/>
<path d="M23.0592 7.11843C21.7785 7.78593 15.1438 10.5141 13.7313 11.2504C12.3188 11.9867 11.5342 11.9795 10.4183 11.4463C9.30253 10.9129 2.24203 8.06062 0.970312 7.45284C-0.301594 6.84515 -0.328125 6.42656 0.921094 5.93728C2.17041 5.44809 9.19219 2.69343 10.6763 2.16093C12.1601 1.62853 12.6749 1.6094 13.9377 2.07206C15.2006 2.53472 21.7958 5.15962 23.0437 5.61684C24.292 6.07396 24.3399 6.45093 23.0592 7.11843Z" fill="#C6302B"/>
<path d="M14.9328 4.75847L12.8693 4.97269L12.4074 6.08419L11.6614 4.84388L9.27872 4.62975L11.0566 3.9886L10.5232 3.00441L12.1877 3.65541L13.7569 3.14166L13.3328 4.15932L14.9328 4.75847ZM12.2843 10.1508L8.43328 8.55357L13.9514 7.70653L12.2843 10.1508ZM6.94519 5.37628C8.57409 5.37628 9.89456 5.88816 9.89456 6.51947C9.89456 7.15097 8.57409 7.66275 6.94519 7.66275C5.31628 7.66275 3.99581 7.15088 3.99581 6.51947C3.99581 5.88816 5.31628 5.37628 6.94519 5.37628Z" fill="white"/>
<path d="M17.3714 5.06231L20.6373 6.35287L17.3742 7.64222L17.3714 5.06231Z" fill="#621B1C"/>
<path d="M13.7583 6.49153L17.3714 5.06231L17.3742 7.64222L17.0199 7.78078L13.7583 6.49153Z" fill="#9A2928"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,88 @@
{
"id": "redis",
"title": "Redis",
"description": "Monitor redis using logs and metrics.",
"author": {
"name": "SigNoz",
"email": "integrations@signoz.io",
"homepage": "https://signoz.io"
},
"icon": "file://icon.svg",
"categories": [
"Database"
],
"overview": "file://overview.md",
"configuration": [
{
"title": "Prerequisites",
"instructions": "file://config/prerequisites.md"
},
{
"title": "Configure Otel Collector",
"instructions": "file://config/configure-otel-collector.md"
}
],
"assets": {
"logs": {
"pipelines": [
"file://assets/pipelines/log-parser.json"
]
},
"dashboards": [
"file://assets/dashboards/overview.json"
],
"alerts": []
},
"connection_tests": {
"logs": {
"op": "AND",
"items": [
{
"key": {
"type": "tag",
"key": "source",
"dataType": "string"
},
"op": "=",
"value": "redis"
}
]
}
},
"data_collected": {
"logs": [
{
"name": "Request Method",
"path": "attributes[\"http.request.method\"]",
"type": "string",
"description": "HTTP method"
},
{
"name": "Request Path",
"path": "attributes[\"url.path\"]",
"type": "string",
"description": "path requested"
},
{
"name": "Response Status Code",
"path": "attributes[\"http.response.status_code\"]",
"type": "int",
"description": "HTTP response code"
}
],
"metrics": [
{
"name": "http.server.request.duration",
"type": "Histogram",
"unit": "s",
"description": "Duration of HTTP server requests"
},
{
"name": "http.server.active_requests",
"type": "UpDownCounter",
"unit": "{ request }",
"description": "Number of active HTTP server requests"
}
]
}
}

View File

@ -0,0 +1,3 @@
### Monitor Redis with SigNoz
Parse your Redis logs and collect key metrics.

View File

@ -0,0 +1,32 @@
package integrations
import (
"context"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestBuiltinIntegrations(t *testing.T) {
require := require.New(t)
repo := BuiltInIntegrations{}
builtins, apiErr := repo.list(context.Background())
require.Nil(apiErr)
require.Greater(
len(builtins), 0,
"some built in integrations are expected to be bundled.",
)
nginxIntegrationId := "builtin::nginx"
res, apiErr := repo.get(context.Background(), []string{
nginxIntegrationId,
})
require.Nil(apiErr)
nginxIntegration, exists := res[nginxIntegrationId]
require.True(exists)
require.False(strings.HasPrefix(nginxIntegration.Overview, "file://"))
}

View File

@ -86,6 +86,12 @@ type UninstallIntegrationRequest struct {
func (c *Controller) Uninstall(
ctx context.Context, req *UninstallIntegrationRequest,
) *model.ApiError {
if len(req.IntegrationId) < 1 {
return model.BadRequest(fmt.Errorf(
"integration_id is required.",
))
}
return c.mgr.UninstallIntegration(
ctx, req.IntegrationId,
)

View File

@ -122,8 +122,7 @@ func NewManager(db *sqlx.DB) (*Manager, error) {
}
return &Manager{
// TODO(Raj): Hook up a real available integrations provider.
availableIntegrationsRepo: &TestAvailableIntegrationsRepo{},
availableIntegrationsRepo: &BuiltInIntegrations{},
installedIntegrationsRepo: iiRepo,
}, nil
}