-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES output: allow to use tag values on index name #3470
Merged
Merged
Changes from 4 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
4e90ba0
ES output: allow to use tag values on index name
lpic10 30ab7f3
Fix bug when end tag is not present
lpic10 16e3f03
Change notation to {{ .. }}
lpic10 42e2ad7
Update template pattern
lpic10 1e66553
Retrieve tag keys at connect time
lpic10 4b311f4
Small changes
lpic10 dd67ed7
Merge branch 'master' of https://github.com/influxdata/telegraf into …
lpic10 67b1d8d
Updated README
lpic10 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,20 +3,22 @@ package elasticsearch | |
import ( | ||
"context" | ||
"fmt" | ||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/internal" | ||
"github.com/influxdata/telegraf/plugins/outputs" | ||
"gopkg.in/olivere/elastic.v5" | ||
"log" | ||
"net/http" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/internal" | ||
"github.com/influxdata/telegraf/plugins/outputs" | ||
"gopkg.in/olivere/elastic.v5" | ||
) | ||
|
||
type Elasticsearch struct { | ||
URLs []string `toml:"urls"` | ||
IndexName string | ||
DefaultTagValue string | ||
Username string | ||
Password string | ||
EnableSniffer bool | ||
|
@@ -37,7 +39,7 @@ var sampleConfig = ` | |
## Multiple urls can be specified as part of the same cluster, | ||
## this means that only ONE of the urls will be written to each interval. | ||
urls = [ "http://node1.es.example.com:9200" ] # required. | ||
## Elasticsearch client timeout, defaults to "5s" if not set. | ||
## Elasticsearch client timeout, defaults to "5s" if not set. | ||
timeout = "5s" | ||
## Set to true to ask Elasticsearch a list of all cluster nodes, | ||
## thus it is not necessary to list all nodes in the urls config option. | ||
|
@@ -58,6 +60,11 @@ var sampleConfig = ` | |
# %m - month (01..12) | ||
# %d - day of month (e.g., 01) | ||
# %H - hour (00..23) | ||
## Additionally, you can specify a tag name using the notation {{tag_name}} | ||
## which will be used as part of the index name. If the tag does not exist, | ||
## the default tag value will be used. | ||
# index_name = "telegraf-{{host}}-%Y.%m.%d" | ||
# default_tag_value = "none" | ||
index_name = "telegraf-%Y.%m.%d" # required. | ||
|
||
## Optional SSL Config | ||
|
@@ -165,7 +172,7 @@ func (a *Elasticsearch) Write(metrics []telegraf.Metric) error { | |
|
||
// index name has to be re-evaluated each time for telegraf | ||
// to send the metric to the correct time-based index | ||
indexName := a.GetIndexName(a.IndexName, metric.Time()) | ||
indexName := a.GetIndexName(a.IndexName, metric.Time(), metric.Tags()) | ||
|
||
m := make(map[string]interface{}) | ||
|
||
|
@@ -212,13 +219,21 @@ func (a *Elasticsearch) manageTemplate(ctx context.Context) error { | |
return fmt.Errorf("Elasticsearch template check failed, template name: %s, error: %s", a.TemplateName, errExists) | ||
} | ||
|
||
templatePattern := a.IndexName + "*" | ||
templatePattern := a.IndexName | ||
|
||
if strings.Contains(templatePattern, "%") { | ||
templatePattern = templatePattern[0:strings.Index(templatePattern, "%")] | ||
} | ||
|
||
if strings.Contains(a.IndexName, "%") { | ||
templatePattern = a.IndexName[0:strings.Index(a.IndexName, "%")] + "*" | ||
if strings.Contains(templatePattern, "{{") { | ||
templatePattern = templatePattern[0:strings.Index(templatePattern, "{{")] | ||
} | ||
|
||
if (a.OverwriteTemplate) || (!templateExists) { | ||
if templatePattern == "" { | ||
return fmt.Errorf("Template cannot be created for dynamic index names without an index prefix") | ||
} | ||
|
||
if (a.OverwriteTemplate) || (!templateExists) || (templatePattern != "") { | ||
// Create or update the template | ||
tmpl := fmt.Sprintf(` | ||
{ | ||
|
@@ -276,7 +291,7 @@ func (a *Elasticsearch) manageTemplate(ctx context.Context) error { | |
] | ||
} | ||
} | ||
}`, templatePattern) | ||
}`, templatePattern+"*") | ||
_, errCreateTemplate := a.Client.IndexPutTemplate(a.TemplateName).BodyString(tmpl).Do(ctx) | ||
|
||
if errCreateTemplate != nil { | ||
|
@@ -293,7 +308,7 @@ func (a *Elasticsearch) manageTemplate(ctx context.Context) error { | |
return nil | ||
} | ||
|
||
func (a *Elasticsearch) GetIndexName(indexName string, eventTime time.Time) string { | ||
func (a *Elasticsearch) GetIndexName(indexName string, eventTime time.Time, metricTags map[string]string) string { | ||
if strings.Contains(indexName, "%") { | ||
var dateReplacer = strings.NewReplacer( | ||
"%Y", eventTime.UTC().Format("2006"), | ||
|
@@ -306,6 +321,45 @@ func (a *Elasticsearch) GetIndexName(indexName string, eventTime time.Time) stri | |
indexName = dateReplacer.Replace(indexName) | ||
} | ||
|
||
startTag := strings.Index(indexName, "{{") | ||
|
||
for startTag >= 0 { | ||
|
||
endTag := strings.Index(indexName, "}}") | ||
|
||
if endTag < 0 { | ||
|
||
startTag = -1 | ||
|
||
} else { | ||
|
||
tagName := indexName[startTag+2 : endTag] | ||
tagNameTrim := strings.TrimSpace(tagName) | ||
found := false | ||
|
||
for k := range metricTags { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this happens for each metric, I'm concerned about the performance. Perhaps this can be improved with by doing some of the work at Connect time. I'll try to explain in more detail, this part needs only done once:
Then at Write time:
|
||
if k == tagNameTrim { | ||
found = true | ||
var tagReplacer = strings.NewReplacer( | ||
"{{"+tagName+"}}", metricTags[k], | ||
) | ||
indexName = tagReplacer.Replace(indexName) | ||
} | ||
} | ||
|
||
if found != true { | ||
log.Printf("D! Tag %s not found, using '%s' instead\n", tagNameTrim, a.DefaultTagValue) | ||
var tagReplacer = strings.NewReplacer( | ||
"{{"+tagName+"}}", a.DefaultTagValue, | ||
) | ||
indexName = tagReplacer.Replace(indexName) | ||
|
||
} | ||
|
||
startTag = strings.Index(indexName, "{{") | ||
} | ||
} | ||
|
||
return indexName | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we trim the space here, then I think the tag may not match further down in the replacer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's why I kept the the
tagName
variable to be used by the replacer instead of trimming on it directly