PageRenderTime 67ms CodeModel.GetById 1ms RepoModel.GetById 1ms app.codeStats 6ms

/pipeline/message_template.go

https://gitlab.com/karouf/heka
Go | 116 lines | 79 code | 8 blank | 29 comment | 19 complexity | c27cb7bb9e3d3dc9f64b1256c06991b0 MD5 | raw file
  1. /***** BEGIN LICENSE BLOCK *****
  2. # This Source Code Form is subject to the terms of the Mozilla Public
  3. # License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. # You can obtain one at http://mozilla.org/MPL/2.0/.
  5. #
  6. # The Initial Developer of the Original Code is the Mozilla Foundation.
  7. # Portions created by the Initial Developer are Copyright (C) 2012
  8. # the Initial Developer. All Rights Reserved.
  9. #
  10. # Contributor(s):
  11. # Rob Miller (rmiller@mozilla.com)
  12. #
  13. # ***** END LICENSE BLOCK *****/
  14. package pipeline
  15. import (
  16. "errors"
  17. "fmt"
  18. "regexp"
  19. "strconv"
  20. "strings"
  21. "github.com/mozilla-services/heka/message"
  22. "github.com/pborman/uuid"
  23. )
  24. // Populated by the init function, this regex matches the MessageFields values
  25. // to interpolate variables from capture groups or other parts of the existing
  26. // message.
  27. var varMatcher *regexp.Regexp
  28. // Common type used to specify a set of values with which to populate a
  29. // message object. The keys represent message fields, the values can be
  30. // interpolated w/ capture parts from a message matcher.
  31. type MessageTemplate map[string]string
  32. // Applies this message template's values to the provided message object,
  33. // interpolating the provided substitutions into the values in the process.
  34. func (mt MessageTemplate) PopulateMessage(msg *message.Message, subs map[string]string) error {
  35. var val string
  36. for field, rawVal := range mt {
  37. if subs == nil {
  38. val = rawVal
  39. } else {
  40. val = InterpolateString(rawVal, subs)
  41. }
  42. switch field {
  43. case "Logger":
  44. msg.SetLogger(val)
  45. case "Type":
  46. msg.SetType(val)
  47. case "Payload":
  48. msg.SetPayload(val)
  49. case "Hostname":
  50. msg.SetHostname(val)
  51. case "Pid":
  52. intPart := strings.Split(val, ".")[0]
  53. pid, err := strconv.ParseInt(intPart, 10, 32)
  54. if err != nil {
  55. return err
  56. }
  57. msg.SetPid(int32(pid))
  58. case "Severity":
  59. severity, err := strconv.ParseInt(val, 10, 32)
  60. if err != nil {
  61. return err
  62. }
  63. msg.SetSeverity(int32(severity))
  64. case "Uuid":
  65. if len(val) == message.UUID_SIZE {
  66. msg.SetUuid([]byte(val))
  67. } else {
  68. if uuidBytes := uuid.Parse(val); uuidBytes == nil {
  69. return errors.New("Invalid UUID string.")
  70. } else {
  71. msg.SetUuid(uuidBytes)
  72. }
  73. }
  74. default:
  75. fi := strings.SplitN(field, "|", 2)
  76. if len(fi) < 2 {
  77. fi = append(fi, "")
  78. }
  79. f, err := message.NewField(fi[0], val, fi[1])
  80. msg.AddField(f)
  81. if err != nil {
  82. return err
  83. }
  84. }
  85. }
  86. return nil
  87. }
  88. // Given a regular expression, return the string resulting from interpolating
  89. // variables that exist in matchParts
  90. //
  91. // Example input to a formatRegexp: Reported at %Hostname% by %Reporter%
  92. // Assuming there are entries in matchParts for 'Hostname' and 'Reporter', the
  93. // returned string will then be: Reported at Somehost by Jonathon
  94. func InterpolateString(formatRegexp string, subs map[string]string) (newString string) {
  95. return varMatcher.ReplaceAllStringFunc(formatRegexp,
  96. func(matchWord string) string {
  97. // Remove the preceding and trailing %
  98. m := matchWord[1 : len(matchWord)-1]
  99. if repl, ok := subs[m]; ok {
  100. return repl
  101. }
  102. return fmt.Sprintf("<%s>", m)
  103. })
  104. }
  105. // Initialize the varMatcher for use in InterpolateString
  106. func init() {
  107. varMatcher, _ = regexp.Compile("%\\w+%")
  108. }