Skip to content

Commit 7a2683e

Browse files
committed
Update the kibana link code to use the new, cleaner Kibana URL
1 parent 2d23374 commit 7a2683e

3 files changed

Lines changed: 91 additions & 151 deletions

File tree

servicex/app/transforms.py

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2727
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828
import asyncio
29+
import urllib.parse
30+
from urllib.parse import urlunparse
2931
from pathlib import Path
3032
from typing import Optional, List
3133
import webbrowser
@@ -233,58 +235,44 @@ class LogLevel(str, Enum):
233235
Level of the log messages: INFO & ERROR
234236
"""
235237

236-
info = ("INFO",)
237-
error = ("ERROR",)
238+
info = "INFO"
239+
error = "ERROR"
238240

239241

240-
def add_query(key, value):
242+
def create_kibana_link_parameters(
243+
log_url, transform_id=None, log_level: LogLevel = LogLevel.error
244+
):
241245
"""
242-
Creates query string from the key and value pairs
246+
Add a filter to a Kibana dashboard URL to show only results for a given request ID
247+
with an ERROR level or higher.
243248
"""
244-
query_string = "(query:(match_phrase:({0}:'{1}')))".format(key, value)
245-
return query_string
249+
decoded_url = urllib.parse.urlparse(log_url)
246250

251+
view_match = re.search(r"/view/([^?]+)", decoded_url.fragment)
252+
instance_match = re.search(r"instance:([^)]+)", decoded_url.fragment)
253+
index_match = re.search(r"index:'([^']+)'", decoded_url.fragment)
247254

248-
def select_time(time_frame=TimeFrame.day):
249-
"""
250-
Takes input as 'day','week','month' and returns the time filter
251-
"""
252-
time_string = time_frame
253-
if time_frame.lower() == TimeFrame.day:
254-
time_string = "time:(from:now%2Fd,to:now%2Fd)"
255-
elif time_frame.lower() == TimeFrame.week:
256-
time_string = "time:(from:now%2Fw,to:now%2Fw)"
257-
elif time_frame.lower() == TimeFrame.month:
258-
time_string = "time:(from:now-30d%2Fd,to:now)"
259-
else:
260-
rich.print("Got a time frame apart from 'day', 'week', 'month'")
261-
return time_string
255+
view = view_match.group(1) if view_match else None
256+
instance = instance_match.group(1) if instance_match else None
257+
index = index_match.group(1) if index_match else None
262258

259+
# If we are unable to parse the fragment, return the original URL
260+
if view is None or instance is None or index is None:
261+
return log_url
263262

264-
def create_kibana_link_parameters(
265-
log_url, transform_id=None, log_level=None, time_frame=None
266-
):
267-
"""
268-
Create the _a and _g parameters for the kibana dashboard link
269-
"""
270-
if log_level:
271-
a_parameter = (
272-
f"&_a=(filters:!({add_query('requestId', transform_id)},"
273-
f"{add_query('level', log_level.value.lower())}))"
274-
)
275-
else:
276-
a_parameter = f"&_a=(filters:!({add_query('requestId', transform_id)}))"
277-
g_parameter = f"&_g=({select_time(time_frame.value.lower())})"
278-
kibana_link = re.sub(r"\&\_g\=\(\)", g_parameter + a_parameter, log_url)
279-
return kibana_link
263+
_a = f"(filters:!((query:(match_phrase:(instance:{instance}))),(query:(match_phrase:(requestId:'{transform_id}'))),(query:(match_phrase:(level:{log_level.value})))),index:'{index}')" # NOQA E502
264+
265+
new_fragment = f"/view/{view}?embed=true&_g=(filters:!(),refreshInterval:(pause:!t,value:1000),time:(from:now-24h/h,to:now))" # NOQA E502
266+
new_fragment += f"&_a={urllib.parse.quote(_a)}"
267+
decoded_url = decoded_url._replace(fragment=new_fragment)
268+
return urlunparse(decoded_url)
280269

281270

282271
@transforms_app.command(no_args_is_help=True)
283272
def logs(
284273
backend: Optional[str] = backend_cli_option,
285274
transform_id: str = transform_id_arg,
286275
log_level: Optional[LogLevel] = log_level_opt,
287-
time_frame: Optional[TimeFrame] = time_frame_opt,
288276
):
289277
"""
290278
Open the URL to the Kibana dashboard of the logs of a tranformer
@@ -293,10 +281,7 @@ def logs(
293281
transforms = sx.get_transform_status(transform_id)
294282
if transforms and transforms.request_id == transform_id:
295283
kibana_link = create_kibana_link_parameters(
296-
transforms.log_url,
297-
transform_id=transform_id,
298-
log_level=log_level,
299-
time_frame=time_frame,
284+
transforms.log_url, transform_id=transform_id, log_level=log_level
300285
)
301286
print(kibana_link)
302287
webbrowser.open(kibana_link)

servicex/query_core.py

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,7 @@ async def submit_and_download(
183183
:return: Transform results object which contains the list of files downloaded
184184
or the list of pre-signed urls
185185
"""
186-
from servicex.app.transforms import (
187-
create_kibana_link_parameters,
188-
TimeFrame,
189-
LogLevel,
190-
)
186+
from servicex.app.transforms import create_kibana_link_parameters
191187

192188
download_files_task = None
193189
loop = asyncio.get_running_loop()
@@ -240,10 +236,7 @@ def transform_complete(task: Task):
240236
)
241237
if self.current_status.log_url is not None:
242238
kibana_link = create_kibana_link_parameters(
243-
self.current_status.log_url,
244-
self.current_status.request_id,
245-
LogLevel.error,
246-
TimeFrame.month,
239+
self.current_status.log_url, self.current_status.request_id
247240
)
248241
logger.error(
249242
f"More information of '{self.title}' [bold red on white][link={kibana_link}]HERE[/link][/bold red on white]" # NOQA: E501
@@ -412,11 +405,7 @@ async def transform_status_listener(
412405
of status. Once we know the number of files in the dataset, update the progress
413406
bars.
414407
"""
415-
from servicex.app.transforms import (
416-
LogLevel,
417-
create_kibana_link_parameters,
418-
TimeFrame,
419-
)
408+
from servicex.app.transforms import create_kibana_link_parameters
420409

421410
# Actual number of files in the dataset. We only know this once the DID
422411
# finder has completed its work. In the meantime transformers will already
@@ -476,8 +465,6 @@ async def transform_status_listener(
476465
kibana_link = create_kibana_link_parameters(
477466
self.current_status.log_url,
478467
self.current_status.request_id,
479-
LogLevel.error,
480-
TimeFrame.month,
481468
)
482469
logger.warning(
483470
f"More logfiles of '{self.title}' [bold red on white]"
@@ -504,10 +491,7 @@ async def transform_status_listener(
504491
err_str = f"Request {titlestr}was canceled"
505492
if self.current_status.log_url is not None:
506493
kibana_link = create_kibana_link_parameters(
507-
self.current_status.log_url,
508-
self.current_status.request_id,
509-
LogLevel.error,
510-
TimeFrame.month,
494+
self.current_status.log_url, self.current_status.request_id
511495
)
512496
logger.error(
513497
f"{err_str}\nMore logfiles of '{self.title}' [bold red on white][link={kibana_link}]HERE[/link][/bold red on white]" # NOQA: E501
@@ -549,10 +533,7 @@ async def transform_status_listener(
549533
)
550534
if self.current_status.log_url is not None:
551535
kibana_link = create_kibana_link_parameters(
552-
self.current_status.log_url,
553-
self.current_status.request_id,
554-
LogLevel.error,
555-
TimeFrame.month,
536+
self.current_status.log_url, self.current_status.request_id
556537
)
557538
logger.error(
558539
f"More logfiles of '{self.title}' [bold red on white][link={kibana_link}]HERE[/link][/bold red on white]" # NOQA: E501
@@ -562,10 +543,7 @@ async def transform_status_listener(
562543
err_str = f"Fatal issue in ServiceX server for request {titlestr}"
563544
if self.current_status.log_url is not None:
564545
kibana_link = create_kibana_link_parameters(
565-
self.current_status.log_url,
566-
self.current_status.request_id,
567-
LogLevel.error,
568-
TimeFrame.month,
546+
self.current_status.log_url, self.current_status.request_id
569547
)
570548
logger.error(
571549
f"{err_str}\nMore logfiles of '{self.title}' [bold red on white][link={kibana_link}]HERE[/link][/bold red on white]" # NOQA: E501
Lines changed: 59 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,73 @@
1-
from servicex.app.transforms import LogLevel, TimeFrame
2-
from servicex.app.transforms import (
3-
add_query,
4-
select_time,
5-
create_kibana_link_parameters,
6-
)
1+
from servicex.app.transforms import LogLevel, create_kibana_link_parameters
72

83

9-
def test_add_query():
10-
key = "abc"
11-
value = "123-345-567"
12-
query = "(query:(match_phrase:(abc:'123-345-567')))"
13-
assert add_query(key, value) == query
4+
class TestAddRequestIdFilter:
5+
"""Tests for add_request_id_filter using a real Kibana dashboard URL."""
146

15-
key = "requestId"
16-
value = "d2ede739-9779-4075-95b1-0c7fae1de408"
17-
query = "(query:(match_phrase:(requestId:'d2ede739-9779-4075-95b1-0c7fae1de408')))"
18-
assert add_query(key, value) == query
7+
EXAMPLE_URL = (
8+
"https://atlas-kibana.mwt2.org:5601/s/servicex/app/dashboards"
9+
"?auth_provider_hint=anonymous1#/view/bb682100-5558-11ed-afcf-d91dad577662#"
10+
"?embed=true"
11+
"&_g=(filters:!(),refreshInterval:(pause:!t,value:1000),"
12+
"time:(from:now-24h/h,to:now))"
13+
"&_a=(filters:!((query:(match_phrase:(instance:servicex-unit-test))))"
14+
",index:'923eaa00-45b9-11ed-afcf-d91dad577662')"
15+
)
1916

17+
def test_preserves_base_url(self):
18+
result = create_kibana_link_parameters(
19+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
20+
)
21+
assert result.startswith(
22+
"https://atlas-kibana.mwt2.org:5601/s/servicex/app/dashboards"
23+
)
2024

21-
def test_select_time():
22-
time_frame = TimeFrame.week
23-
time_filter = "time:(from:now%2Fw,to:now%2Fw)"
24-
assert time_filter == select_time(time_frame)
25+
def test_preserves_auth_query(self):
26+
result = create_kibana_link_parameters(
27+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
28+
)
29+
assert "?auth_provider_hint=anonymous1" in result
2530

26-
time_frame = "month"
27-
time_filter = "time:(from:now-30d%2Fd,to:now)"
28-
assert time_filter == select_time(time_frame)
31+
def test_preserves_view_path(self):
32+
result = create_kibana_link_parameters(
33+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
34+
)
35+
assert "#/view/bb682100-5558-11ed-afcf-d91dad577662" in result
2936

30-
time_frame = "daY"
31-
time_filter = "time:(from:now%2Fd,to:now%2Fd)"
32-
assert time_filter == select_time(time_frame)
37+
def test_includes_embed_true(self):
38+
result = create_kibana_link_parameters(
39+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
40+
)
41+
assert "embed=true" in result
3342

43+
def test_preserves_instance_in_query(self):
44+
result = create_kibana_link_parameters(
45+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
46+
)
47+
assert "servicex-unit-test" in result
3448

35-
def test_create_kibana_link_parameters():
36-
initial_log_url = (
37-
"https://atlas-kibana.mwt2.org:5601/s/servicex/app"
38-
"/dashboards?auth_provider_hint=anonymous1#/view/"
39-
"2d2b3b40-f34e-11ed-a6d8-9f6a16cd6d78?embed=true&_g=()"
40-
"&show-time-filter=true&hide-filter-bar=true"
41-
)
42-
transform_id = "d2ede739-9779-4075-95b1-0c7fae1de408"
43-
log_level = LogLevel.error
44-
time_frame = TimeFrame.day
45-
final_url = (
46-
"https://atlas-kibana.mwt2.org:5601/s/servicex/app/dashboards?"
47-
"auth_provider_hint=anonymous1#/view/2d2b3b40-f34e-11ed-a6d8-9f6a16cd6d78?"
48-
"embed=true&_g=(time:(from:now%2Fd,to:now%2Fd))"
49-
"&_a=(filters:!((query:(match_phrase:"
50-
"(requestId:'d2ede739-9779-4075-95b1-0c7fae1de408'))),"
51-
"(query:(match_phrase:(level:'error')))))&show-time-filter=true"
52-
"&hide-filter-bar=true"
53-
)
54-
assert (
55-
create_kibana_link_parameters(
56-
initial_log_url, transform_id, log_level, time_frame
49+
def test_includes_request_id_in_query(self):
50+
result = create_kibana_link_parameters(
51+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
5752
)
58-
== final_url
59-
)
53+
assert "abc-123" in result
6054

61-
transform_id = "93713b34-2f0b-4d53-8412-8afa98626516"
62-
log_level = LogLevel.info
63-
time_frame = TimeFrame.month
64-
final_url = (
65-
"https://atlas-kibana.mwt2.org:5601/s/servicex/app/dashboards?"
66-
"auth_provider_hint=anonymous1#/view/2d2b3b40-f34e-11ed-a6d8-9f6a16cd6d78?"
67-
"embed=true&_g=(time:(from:now-30d%2Fd,to:now))"
68-
"&_a=(filters:!((query:(match_phrase:"
69-
"(requestId:'93713b34-2f0b-4d53-8412-8afa98626516'))),"
70-
"(query:(match_phrase:(level:'info')))))&show-time-filter=true"
71-
"&hide-filter-bar=true"
72-
)
73-
assert (
74-
create_kibana_link_parameters(
75-
initial_log_url, transform_id, log_level, time_frame
55+
def test_includes_log_level_in_query(self):
56+
result = create_kibana_link_parameters(
57+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.error
7658
)
77-
== final_url
78-
)
59+
assert "level%3AERROR" in result
7960

80-
transform_id = "93713b34-2f0b-4d53-8412-8afa98626516"
81-
log_level = None
82-
time_frame = TimeFrame.month
83-
final_url = (
84-
"https://atlas-kibana.mwt2.org:5601/s/servicex/app/dashboards?"
85-
"auth_provider_hint=anonymous1#/view/2d2b3b40-f34e-11ed-a6d8-9f6a16cd6d78?"
86-
"embed=true&_g=(time:(from:now-30d%2Fd,to:now))"
87-
"&_a=(filters:!((query:(match_phrase:"
88-
"(requestId:'93713b34-2f0b-4d53-8412-8afa98626516')))))"
89-
"&show-time-filter=true&hide-filter-bar=true"
90-
)
91-
assert (
92-
create_kibana_link_parameters(
93-
initial_log_url, transform_id, log_level, time_frame
61+
def test_includes_app_state_filter(self):
62+
result = create_kibana_link_parameters(
63+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
9464
)
95-
== final_url
96-
)
65+
assert "_a=" in result
66+
assert "requestId" in result
67+
68+
def test_preserves_time_range(self):
69+
result = create_kibana_link_parameters(
70+
self.EXAMPLE_URL, "abc-123", log_level=LogLevel.info
71+
)
72+
assert "now-24h/h" in result
73+
assert "to:now" in result

0 commit comments

Comments
 (0)