You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
4.1 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
4 years ago
  1. package command
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/pb"
  5. "github.com/golang/protobuf/jsonpb"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "time"
  10. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  11. "github.com/chrislusf/seaweedfs/weed/security"
  12. "github.com/chrislusf/seaweedfs/weed/util"
  13. )
  14. func init() {
  15. cmdFilerMetaTail.Run = runFilerMetaTail // break init cycle
  16. }
  17. var cmdFilerMetaTail = &Command{
  18. UsageLine: "filer.meta.tail [-filer=localhost:8888] [-pathPrefix=/]",
  19. Short: "see continuous changes on a filer",
  20. Long: `See continuous changes on a filer.
  21. weed filer.meta.tail -timeAgo=30h | grep truncate
  22. weed filer.meta.tail -timeAgo=30h | jq .
  23. weed filer.meta.tail -timeAgo=30h | jq .eventNotification.newEntry.name
  24. weed filer.meta.tail -timeAgo=30h -es=http://<elasticSearchServerHost>:<port> -es.index=seaweedfs
  25. `,
  26. }
  27. var (
  28. tailFiler = cmdFilerMetaTail.Flag.String("filer", "localhost:8888", "filer hostname:port")
  29. tailTarget = cmdFilerMetaTail.Flag.String("pathPrefix", "/", "path to a folder or common prefix for the folders or files on filer")
  30. tailStart = cmdFilerMetaTail.Flag.Duration("timeAgo", 0, "start time before now. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\"")
  31. tailStop = cmdFilerMetaTail.Flag.Duration("untilTimeAgo", 0, "read until this time ago. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\"")
  32. tailPattern = cmdFilerMetaTail.Flag.String("pattern", "", "full path or just filename pattern, ex: \"/home/?opher\", \"*.pdf\", see https://golang.org/pkg/path/filepath/#Match ")
  33. esServers = cmdFilerMetaTail.Flag.String("es", "", "comma-separated elastic servers http://<host:port>")
  34. esIndex = cmdFilerMetaTail.Flag.String("es.index", "seaweedfs", "ES index name")
  35. )
  36. func runFilerMetaTail(cmd *Command, args []string) bool {
  37. util.LoadConfiguration("security", false)
  38. grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
  39. clientId := util.RandomInt32()
  40. var filterFunc func(dir, fname string) bool
  41. if *tailPattern != "" {
  42. if strings.Contains(*tailPattern, "/") {
  43. println("watch path pattern", *tailPattern)
  44. filterFunc = func(dir, fname string) bool {
  45. matched, err := filepath.Match(*tailPattern, dir+"/"+fname)
  46. if err != nil {
  47. fmt.Printf("error: %v", err)
  48. }
  49. return matched
  50. }
  51. } else {
  52. println("watch file pattern", *tailPattern)
  53. filterFunc = func(dir, fname string) bool {
  54. matched, err := filepath.Match(*tailPattern, fname)
  55. if err != nil {
  56. fmt.Printf("error: %v", err)
  57. }
  58. return matched
  59. }
  60. }
  61. }
  62. shouldPrint := func(resp *filer_pb.SubscribeMetadataResponse) bool {
  63. if filer_pb.IsEmpty(resp) {
  64. return false
  65. }
  66. if filterFunc == nil {
  67. return true
  68. }
  69. if resp.EventNotification.OldEntry != nil && filterFunc(resp.Directory, resp.EventNotification.OldEntry.Name) {
  70. return true
  71. }
  72. if resp.EventNotification.NewEntry != nil && filterFunc(resp.EventNotification.NewParentPath, resp.EventNotification.NewEntry.Name) {
  73. return true
  74. }
  75. return false
  76. }
  77. jsonpbMarshaler := jsonpb.Marshaler{
  78. EmitDefaults: false,
  79. }
  80. eachEntryFunc := func(resp *filer_pb.SubscribeMetadataResponse) error {
  81. jsonpbMarshaler.Marshal(os.Stdout, resp)
  82. fmt.Fprintln(os.Stdout)
  83. return nil
  84. }
  85. if *esServers != "" {
  86. var err error
  87. eachEntryFunc, err = sendToElasticSearchFunc(*esServers, *esIndex)
  88. if err != nil {
  89. fmt.Printf("create elastic search client to %s: %+v\n", *esServers, err)
  90. return false
  91. }
  92. }
  93. var untilTsNs int64
  94. if *tailStop != 0 {
  95. untilTsNs = time.Now().Add(-*tailStop).UnixNano()
  96. }
  97. tailErr := pb.FollowMetadata(pb.ServerAddress(*tailFiler), grpcDialOption, "tail", clientId, *tailTarget, nil,
  98. time.Now().Add(-*tailStart).UnixNano(), untilTsNs, 0, func(resp *filer_pb.SubscribeMetadataResponse) error {
  99. if !shouldPrint(resp) {
  100. return nil
  101. }
  102. if err := eachEntryFunc(resp); err != nil {
  103. return err
  104. }
  105. return nil
  106. }, false)
  107. if tailErr != nil {
  108. fmt.Printf("tail %s: %v\n", *tailFiler, tailErr)
  109. }
  110. return true
  111. }