diff --git a/storm-core/src/clj/org/apache/storm/daemon/logviewer.clj b/storm-core/src/clj/org/apache/storm/daemon/logviewer.clj
index 2b80fd87474..7c62b32ca97 100644
--- a/storm-core/src/clj/org/apache/storm/daemon/logviewer.clj
+++ b/storm-core/src/clj/org/apache/storm/daemon/logviewer.clj
@@ -538,13 +538,31 @@
(int (/ (alength needle) -2)))) ;; Addition
:length default-bytes-per-page})))
+(defn url-to-match-centered-in-log-page-daemon-file
+ [needle fname offset port]
+ (let [host (Utils/localHostname)
+ port (logviewer-port)
+ fname (clojure.string/join Utils/FILE_PATH_SEPARATOR (take-last 1 (split fname (re-pattern Utils/FILE_PATH_SEPARATOR))))]
+ (url (str "http://" host ":" port "/daemonlog")
+ {:file fname
+ :start (max 0
+ (- offset
+ (int (/ default-bytes-per-page 2))
+ (int (/ (alength needle) -2)))) ;; Addition
+ :length default-bytes-per-page})))
+
(defnk mk-match-data
[^bytes needle ^ByteBuffer haystack haystack-offset file-offset fname
- :before-bytes nil :after-bytes nil]
- (let [url (url-to-match-centered-in-log-page needle
- fname
- file-offset
- (*STORM-CONF* LOGVIEWER-PORT))
+ :is-daemon false :before-bytes nil :after-bytes nil]
+ (let [url (if is-daemon
+ (url-to-match-centered-in-log-page-daemon-file needle
+ fname
+ file-offset
+ (*STORM-CONF* LOGVIEWER-PORT))
+ (url-to-match-centered-in-log-page needle
+ fname
+ file-offset
+ (*STORM-CONF* LOGVIEWER-PORT)))
haystack-bytes (.array haystack)
before-string (if (>= haystack-offset grep-context-size)
(String. haystack-bytes
@@ -640,7 +658,7 @@
"As the file is read into a buffer, 1/2 the buffer's size at a time, we
search the buffer for matches of the substring and return a list of zero or
more matches."
- [file file-len offset-to-buf init-buf-offset stream bytes-skipped
+ [is-daemon file file-len offset-to-buf init-buf-offset stream bytes-skipped
bytes-read ^ByteBuffer haystack ^bytes needle initial-matches num-matches
^bytes before-bytes]
(loop [buf-offset init-buf-offset
@@ -665,6 +683,7 @@
offset
file-offset
(.getCanonicalPath file)
+ :is-daemon is-daemon
:before-bytes before-arg
:after-bytes after-arg))))
(let [before-str-to-offset (min (.limit haystack)
@@ -721,7 +740,7 @@
context lines. Other information is included to be useful for progressively
searching through a file for display in a UI. The search string must
grep-max-search-size bytes or fewer when decoded with UTF-8."
- [file ^String search-string :num-matches 10 :start-byte-offset 0]
+ [file ^String search-string :is-daemon false :num-matches 10 :start-byte-offset 0]
{:pre [(not (empty? search-string))
(<= (count (.getBytes search-string "UTF-8")) grep-max-search-size)]}
(let [zip-file? (.endsWith (.getName file) ".gz")
@@ -756,7 +775,9 @@
byte-offset start-byte-offset
before-bytes nil]
(let [[matches new-byte-offset new-before-bytes]
- (buffer-substring-search! file
+ (buffer-substring-search!
+ is-daemon
+ file
file-len
byte-offset
init-buf-offset
@@ -783,16 +804,17 @@
new-buf-offset
new-byte-offset
new-before-bytes))
- (mk-grep-response search-bytes
- start-byte-offset
- matches
- (if-not (and (< (count matches) num-matches)
- (>= @total-bytes-read file-len))
- (let [next-byte-offset (+ (get (last matches)
- "byteOffset")
- (alength search-bytes))]
- (if (> file-len next-byte-offset)
- next-byte-offset)))))))))
+ (merge {"isDaemon" (if is-daemon "yes" "no")}
+ (mk-grep-response search-bytes
+ start-byte-offset
+ matches
+ (if-not (and (< (count matches) num-matches)
+ (>= @total-bytes-read file-len))
+ (let [next-byte-offset (+ (get (last matches)
+ "byteOffset")
+ (alength search-bytes))]
+ (if (> file-len next-byte-offset)
+ next-byte-offset))))))))))
(defn- try-parse-int-param
[nam value]
@@ -805,7 +827,7 @@
throw))))
(defn search-log-file
- [fname user ^String root-dir search num-matches offset callback origin]
+ [fname user ^String root-dir is-daemon search num-matches offset callback origin]
(let [file (.getCanonicalFile (File. root-dir fname))]
(if (.exists file)
(if (or (blank? (*STORM-CONF* UI-FILTER))
@@ -819,10 +841,13 @@
(if (and (not (empty? search))
<= (count (.getBytes search "UTF-8")) grep-max-search-size)
(json-response
- (substring-search file
- search
- :num-matches num-matches-int
- :start-byte-offset offset-int)
+ (merge {"isDaemon" (if is-daemon "yes" "no")}
+ (substring-search file
+ search
+ :is-daemon is-daemon
+ :num-matches num-matches-int
+ :start-byte-offset offset-int))
+
callback
:headers {"Access-Control-Allow-Origin" origin
"Access-Control-Allow-Credentials" "true"})
@@ -1090,10 +1115,12 @@
;; :keys list, or this rule could stop working when an authentication
;; filter is configured.
(try
- (let [user (.getUserName http-creds-handler servlet-request)]
+ (let [user (.getUserName http-creds-handler servlet-request)
+ is-daemon (= (:is-daemon m) "yes")]
(search-log-file (URLDecoder/decode file)
user
- (if (= (:is-daemon m) "yes") daemonlog-root log-root)
+ (if is-daemon daemonlog-root log-root)
+ is-daemon
(:search-string m)
(:num-matches m)
(:start-byte-offset m)
diff --git a/storm-core/src/ui/public/logviewer_search.html b/storm-core/src/ui/public/logviewer_search.html
index f878ab9dd5d..f9814996eed 100644
--- a/storm-core/src/ui/public/logviewer_search.html
+++ b/storm-core/src/ui/public/logviewer_search.html
@@ -47,12 +47,12 @@
var file = $.url("?file");
var search = $.url("?search");
var offset = $.url("?offset") || 0;
- var isDaemon = $.url("?is-daemon");
+ var isDaemon = $.url("?is-daemon") || "no";
file = decodeURIComponent(file);
search = decodeURIComponent(search);
$.get("/templates/logviewer-search-page-template.html", function(template) {
- $("#search-form").append(Mustache.render($(template).filter("#search-single-file").html(),{file: file, search: search}));
+ $("#search-form").append(Mustache.render($(template).filter("#search-single-file").html(),{file: file, search: search, isDaemon: isDaemon}));
var result = $("#result");
var url = "/search/"+encodeURIComponent(file)+"?search-string="+search+"&start-byte-offset="+offset+"&is-daemon="+isDaemon;
diff --git a/storm-core/src/ui/public/templates/logviewer-search-page-template.html b/storm-core/src/ui/public/templates/logviewer-search-page-template.html
index 9d208d33348..e1329367fcc 100644
--- a/storm-core/src/ui/public/templates/logviewer-search-page-template.html
+++ b/storm-core/src/ui/public/templates/logviewer-search-page-template.html
@@ -16,7 +16,7 @@
-->
diff --git a/storm-core/test/clj/org/apache/storm/logviewer_test.clj b/storm-core/test/clj/org/apache/storm/logviewer_test.clj
index 1510d194672..e9bada199b6 100644
--- a/storm-core/test/clj/org/apache/storm/logviewer_test.clj
+++ b/storm-core/test/clj/org/apache/storm/logviewer_test.clj
@@ -397,10 +397,26 @@
27526
8888)))))
+ (testing "Logviewer link centers the match in the page (daemon)"
+ (let [expected-fname "foobar.log"]
+ (is (= (str "http://"
+ expected-host
+ ":"
+ expected-port
+ "/daemonlog?file="
+ expected-fname
+ "&start=1947&length="
+ logviewer/default-bytes-per-page)
+ (logviewer/url-to-match-centered-in-log-page-daemon-file (byte-array 42)
+ expected-fname
+ 27526
+ 8888)))))
+
(let [file (->> "logviewer-search-context-tests.log.test"
(clojure.java.io/file "src" "dev"))]
(testing "returns correct before/after context"
- (is (= {"searchString" pattern
+ (is (= {"isDaemon" "no"
+ "searchString" pattern
"startByteOffset" 0
"matches" [{"byteOffset" 0
"beforeString" ""
@@ -451,7 +467,8 @@
(let [file (clojure.java.io/file "src" "dev" "small-worker.log.test")]
(testing "a really small log file"
- (is (= {"searchString" pattern
+ (is (= {"isDaemon" "no"
+ "searchString" pattern
"startByteOffset" 0
"matches" [{"byteOffset" 7
"beforeString" "000000 "
@@ -466,10 +483,29 @@
"&start=0&length=51200")}]}
(logviewer/substring-search file pattern)))))
+ (let [file (clojure.java.io/file "src" "dev" "small-worker.log.test")]
+ (testing "a really small log file (daemon)"
+ (is (= {"isDaemon" "yes"
+ "searchString" pattern
+ "startByteOffset" 0
+ "matches" [{"byteOffset" 7
+ "beforeString" "000000 "
+ "afterString" " 000000\n"
+ "matchString" pattern
+ "logviewerURL" (str "http://"
+ expected-host
+ ":"
+ expected-port
+ "/daemonlog?file="
+ (.getName file)
+ "&start=0&length=51200")}]}
+ (logviewer/substring-search file pattern :is-daemon true)))))
+
(let [file (clojure.java.io/file "src" "dev" "test-3072.log.test")]
(testing "no offset returned when file ends on buffer offset"
(let [expected
- {"searchString" pattern
+ {"isDaemon" "no"
+ "searchString" pattern
"startByteOffset" 0
"matches" [{"byteOffset" 3066
"beforeString" (->>
@@ -516,7 +552,8 @@
(is (= num-matches-found (count (get result "matches")))))))
(is
- (= {"nextByteOffset" 6252
+ (= {"isDaemon" "no"
+ "nextByteOffset" 6252
"searchString" pattern
"startByteOffset" 0
"matches" [
@@ -602,7 +639,8 @@
(testing "Correct match offset is returned when skipping bytes"
(let [start-byte-offset 3197]
- (is (= {"nextByteOffset" 6252
+ (is (= {"isDaemon" "no"
+ "nextByteOffset" 6252
"searchString" pattern
"startByteOffset" start-byte-offset
"matches" [{"byteOffset" 6246
@@ -623,7 +661,8 @@
(let [pattern (clojure.string/join (repeat 1024 'X))]
(is
- (= {"nextByteOffset" 6183
+ (= {"isDaemon" "no"
+ "nextByteOffset" 6183
"searchString" pattern
"startByteOffset" 0
"matches" [
@@ -654,7 +693,8 @@
(let [pattern "𐄀𐄁𐄂"]
(is
- (= {"nextByteOffset" 7176
+ (= {"isDaemon" "no"
+ "nextByteOffset" 7176
"searchString" pattern
"startByteOffset" 0
"matches" [
@@ -674,7 +714,8 @@
(testing "Returns 0 matches for unseen pattern"
(let [pattern "Not There"]
- (is (= {"searchString" pattern
+ (is (= {"isDaemon" "no"
+ "searchString" pattern
"startByteOffset" 0
"matches" []}
(logviewer/substring-search file