Skip to content
This repository was archived by the owner on Nov 18, 2024. It is now read-only.

Commit 5ba7fea

Browse files
committed
added custom tags #27
1 parent 4758b44 commit 5ba7fea

File tree

9 files changed

+212
-12
lines changed

9 files changed

+212
-12
lines changed

docs/config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ title = "nmon2influxdb"
33
theme = "darkdoc"
44
metadataformat = "yaml"
55
pygmentsUseClasses = true
6+
PygmentsCodeFences = true
67

78
[params]
89
# General information

docs/content/configuration/file.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ stats_host=""
7272

7373
If you are always querying the same host or applying the same timeframe to your queries you can setup here this values.
7474

75-
##data retention
75+
## data retention
7676

7777
By default, data are kept indefinitely in InfluxDB. It's possible to change it to have data expiration.
7878

@@ -85,3 +85,53 @@ This value is updated each time a import is done.
8585
All data older than what are specified in the retention policy are not kept.
8686

8787
**Note:** it's the timestamp associated with data which matters. If you load data from one year ago and you have a retention policy of 30 days, you will not see the data.
88+
89+
## custom tags
90+
91+
Starting with version [2.1.0](/210_version_released), it's possible to add custom tags to your data by adding a input section in the configuration file:
92+
93+
``` toml
94+
[[input]]
95+
Measurement="PartitionProcessor"
96+
Name="partition"
97+
Match="adxlpar"
98+
[[input.tag]]
99+
Name="datacenter"
100+
Value="DC1"
101+
```
102+
Custom tags are added at import time.
103+
It will add a tag named **datacenter** with value **DC1** if the tag **partition** in the measurement **PartitionProcessor** match the regular expression **adxlpar**.
104+
105+
Attribute's description:
106+
107+
* **Measurement**: it's the measurement where an additional tag could be added
108+
* **Name**: name of the tag to check
109+
* **Match**: the regular expression used to check the tag value. No need to put the regular expression between '/' characters.
110+
111+
It's possible to add multiple tags for the same data:
112+
113+
114+
``` toml
115+
[[input]]
116+
Measurement="PartitionProcessor"
117+
Name="partition"
118+
Match="adxlpar"
119+
[[input.tag]]
120+
Name="datacenter"
121+
Value="DC1"
122+
[[input.tag]]
123+
Name="group"
124+
Value="adx"
125+
```
126+
127+
If you want to match the exact name, use regular expression syntax (^ and $):
128+
129+
``` toml
130+
[[input]]
131+
Measurement="PartitionProcessor"
132+
Name="partition"
133+
Match="^adxlpar1$"
134+
[[input.tag]]
135+
Name="datacenter"
136+
Value="DC1"
137+
```
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
date: 2016-11-30T13:01:53+01:00
3+
title: 2.1.0 version released
4+
type: "news"
5+
url: "/210_version_released"
6+
---
7+
New version released adding custom tags.
8+
9+
<!--more-->
10+
11+
# Custom Tags
12+
13+
add custom tags to your data by adding a input section in the configuration file:
14+
15+
``` toml
16+
[[input]]
17+
Measurement="PartitionProcessor"
18+
Name="partition"
19+
Match="adxlpar"
20+
[[input.tag]]
21+
Name="datacenter"
22+
Value="DC1"
23+
```
24+
Custom tags are added at import time.
25+
It will add a tag named **datacenter** with value **DC1** if the tag **partition** in the measurement **PartitionProcessor** match the regular expression **adxlpar**.
26+
27+
Attribute's description:
28+
29+
* **Measurement**: it's the measurement where an additional tag could be added
30+
* **Name**: name of the tag to check
31+
* **Match**: the regular expression used to check the tag value. No need to put the regular expression between '/' characters.
32+
33+
More informations on the [configuration file page](/configuration/file/).
34+
35+
# enhancements
36+
37+
* added **serial** tag to nmon files to permit grouping by managed system.
38+
* added information message if retention policy is set.
39+
* added error message on configuration file syntax error.

hmc/hmc.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type HMC struct {
3636
Debug bool
3737
ManagedSystemOnly bool
3838
Samples int
39+
TagParsers nmon2influxdblib.TagParsers
3940
}
4041

4142
// Point is a struct to simplify InfluxDB point creation
@@ -74,6 +75,11 @@ func NewHMC(c *cli.Context) *HMC {
7475
hmc.Samples = config.HMCSamples
7576
hmc.Debug = config.Debug
7677
hmc.FilterManagedSystem = config.HMCManagedSystem
78+
79+
if len(config.Inputs) > 0 {
80+
//Build tag parsing
81+
hmc.TagParsers = nmon2influxdblib.ParseInputs(config.Inputs)
82+
}
7783
hmcURL := fmt.Sprintf("https://"+"%s"+":12443", config.HMCServer)
7884
//initialize new http session
7985
hmc.Session = NewSession(config.HMCUser, config.HMCPassword, hmcURL)
@@ -135,6 +141,17 @@ func (hmc *HMC) AddPoint(point Point) {
135141
tags["partition"] = hmc.GlobalPoint.Partition
136142
}
137143
field := map[string]interface{}{"value": value}
144+
145+
// Checking additional tagging
146+
for key, value := range tags {
147+
if _, ok := hmc.TagParsers[point.Name][key]; ok {
148+
for _, tagParser := range hmc.TagParsers[point.Name][key] {
149+
if tagParser.Regexp.MatchString(value) {
150+
tags[tagParser.Name] = tagParser.Value
151+
}
152+
}
153+
}
154+
}
138155
hmc.InfluxDB.AddPoint(point.Name, hmc.GlobalPoint.Timestamp, field, tags)
139156
}
140157

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func main() {
5555
app := cli.NewApp()
5656
app.Name = "nmon2influxdb"
5757
app.Usage = "upload NMON stats to InfluxDB database"
58-
app.Version = "2.0.1"
58+
app.Version = "2.1.0"
5959
app.Commands = []cli.Command{
6060
{
6161
Name: "import",

nmon/import.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
)
2020

2121
var hostRegexp = regexp.MustCompile(`^AAA,host,(\S+)`)
22+
var serialRegexp = regexp.MustCompile(`^AAA,SerialNumber,(\S+)`)
2223
var osRegexp = regexp.MustCompile(`^AAA,.*(Linux|AIX)`)
2324
var timeRegexp = regexp.MustCompile(`^ZZZZ,([^,]+),(.*)$`)
2425
var intervalRegexp = regexp.MustCompile(`^AAA,interval,(\d+)`)
@@ -51,20 +52,26 @@ func Import(c *cli.Context) {
5152
nmonFiles := new(nmon2influxdblib.Files)
5253
nmonFiles.Parse(c.Args(), config.ImportSSHUser, config.ImportSSHKey)
5354

55+
tagParsers := nmon2influxdblib.ParseInputs(config.Inputs)
56+
57+
var userSkipRegexp *regexp.Regexp
58+
if len(config.ImportSkipMetrics) > 0 {
59+
skipped := strings.Replace(config.ImportSkipMetrics, ",", "|", -1)
60+
userSkipRegexp = regexp.MustCompile(skipped)
61+
}
62+
5463
for _, nmonFile := range nmonFiles.Valid() {
5564
var count int64
5665
count = 0
5766
nmon := InitNmon(config, nmonFile)
5867

59-
lines := nmonFile.Content()
60-
61-
var userSkipRegexp *regexp.Regexp
62-
63-
if len(config.ImportSkipMetrics) > 0 {
64-
skipped := strings.Replace(config.ImportSkipMetrics, ",", "|", -1)
65-
userSkipRegexp = regexp.MustCompile(skipped)
68+
if len(config.Inputs) > 0 {
69+
//Build tag parsing
70+
nmon.TagParsers = tagParsers
6671
}
6772

73+
lines := nmonFile.Content()
74+
6875
var last string
6976
filters := new(influxdbclient.Filters)
7077
filters.Add("file", path.Base(nmonFile.Name), "text")
@@ -156,9 +163,19 @@ func Import(c *cli.Context) {
156163
measurement = nameRegexp.ReplaceAllString(name, "")
157164
}
158165

166+
// Checking additional tagging
167+
for key, value := range tags {
168+
if _, ok := nmon.TagParsers[measurement][key]; ok {
169+
for _, tagParser := range nmon.TagParsers[measurement][key] {
170+
if tagParser.Regexp.MatchString(value) {
171+
tags[tagParser.Name] = tagParser.Value
172+
}
173+
}
174+
}
175+
}
159176
influxdb.AddPoint(measurement, timestamp, field, tags)
160177

161-
if influxdb.PointsCount() == 10000 {
178+
if influxdb.PointsCount() == 5000 {
162179
err = influxdb.WritePoints()
163180
nmon2influxdblib.CheckError(err)
164181
count += influxdb.PointsCount()
@@ -204,6 +221,10 @@ func Import(c *cli.Context) {
204221

205222
tags := map[string]string{"host": nmon.Hostname, "name": column, "pid": elems[1], "command": elems[13], "wlm": wlmclass}
206223

224+
if len(nmon.Serial) > 0 {
225+
tags["serial"] = nmon.Serial
226+
}
227+
207228
// try to convert string to integer
208229
converted, parseErr := strconv.ParseFloat(value, 64)
209230
if parseErr != nil {

nmon/nmon.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
// Nmon structure used to manage nmon files
2121
type Nmon struct {
2222
Hostname string
23+
Serial string
2324
OS string
2425
TimeStamps map[string]string
2526
TextContent string
@@ -29,6 +30,7 @@ type Nmon struct {
2930
starttime time.Time
3031
stoptime time.Time
3132
Location *time.Location
33+
TagParsers nmon2influxdblib.TagParsers
3234
}
3335

3436
// DataSerie structure contains the columns and points to insert in InfluxDB
@@ -142,6 +144,12 @@ func InitNmon(config *nmon2influxdblib.Config, nmonFile nmon2influxdblib.File) (
142144
continue
143145
}
144146

147+
if serialRegexp.MatchString(line) {
148+
matched := serialRegexp.FindStringSubmatch(line)
149+
nmon.Serial = strings.ToLower(matched[1])
150+
continue
151+
}
152+
145153
if osRegexp.MatchString(line) {
146154
matched := osRegexp.FindStringSubmatch(line)
147155
nmon.OS = strings.ToLower(matched[1])

nmon2influxdblib/config.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ type Config struct {
5959
Metric string `toml:"metric,omitempty"`
6060
ListFilter string `toml:",omitempty"`
6161
ListHost string `toml:",omitempty"`
62+
Inputs Inputs `toml:"input,omitempty"`
63+
}
64+
65+
// Inputs allows to put multiple input in the configuration file
66+
type Inputs []Input
67+
68+
// Input specify how to apply new filters
69+
type Input struct {
70+
Measurement string
71+
Name string
72+
Match string
73+
Tags Tags `toml:"tag"`
6274
}
6375

6476
// InitConfig setup initial configuration with sane values
@@ -157,9 +169,9 @@ func (config *Config) LoadCfgFile() {
157169
}
158170

159171
if err := toml.Unmarshal(buf, &config); err != nil {
160-
CheckError(err)
172+
fmt.Printf("syntax error in configuration file: %s \n", err.Error())
173+
os.Exit(1)
161174
}
162-
163175
}
164176

165177
// AddDashboardParams initialize default parameters for dashboard
@@ -256,6 +268,7 @@ func (config *Config) GetDB(dbType string) *influxdbclient.InfluxDB {
256268
influxdb := config.ConnectDB(db)
257269

258270
if exist, _ := influxdb.ExistDB(db); exist != true {
271+
fmt.Printf("Creating InfluxDB database %s\n", db)
259272
_, createErr := influxdb.CreateDB(db)
260273
CheckError(createErr)
261274
}
@@ -265,6 +278,7 @@ func (config *Config) GetDB(dbType string) *influxdbclient.InfluxDB {
265278
// Get default retention policy name
266279
policyName, policyErr := influxdb.GetDefaultRetentionPolicy()
267280
CheckError(policyErr)
281+
fmt.Printf("Updating %s retention policy to keep only the last %s days. Timestamp based.\n", policyName, retention)
268282
_, err := influxdb.UpdateRetentionPolicy(policyName, retention, true)
269283
CheckError(err)
270284
}

nmon2influxdblib/parser.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// nmon2influxdb
2+
// author: adejoux@djouxtech.net
3+
4+
package nmon2influxdblib
5+
6+
import (
7+
"fmt"
8+
"regexp"
9+
)
10+
11+
//Tags array
12+
type Tags []Tag
13+
14+
// Tag is a struct to store additional tags
15+
type Tag struct {
16+
Name string
17+
Value string
18+
Regexp *regexp.Regexp `toml:",skip"`
19+
}
20+
21+
// TagParsers access struct : TagParsers[mesurement][tag name]
22+
type TagParsers map[string]map[string]Tags
23+
24+
// ParseInputs process user inputs and compile regular expressions
25+
func ParseInputs(inputs Inputs) TagParsers {
26+
tagParsers := make(TagParsers)
27+
28+
for _, input := range inputs {
29+
tagRegexp, RegCompErr := regexp.Compile(input.Match)
30+
if RegCompErr != nil {
31+
fmt.Printf("could not compile Config Input match parameter %s\n", input.Match)
32+
}
33+
34+
// Intialize if empty struct
35+
if _, ok := tagParsers[input.Measurement]; !ok {
36+
tagParsers[input.Measurement] = make(map[string]Tags)
37+
}
38+
39+
tagger := tagParsers[input.Measurement][input.Name]
40+
41+
for _, tag := range input.Tags {
42+
tag.Regexp = tagRegexp
43+
tagger = append(tagger, tag)
44+
}
45+
46+
tagParsers[input.Measurement][input.Name] = tagger
47+
48+
}
49+
return tagParsers
50+
}

0 commit comments

Comments
 (0)