1010import org .slf4j .Logger ;
1111import org .slf4j .LoggerFactory ;
1212import org .springframework .core .io .Resource ;
13+ import java .nio .file .StandardCopyOption ;
14+ import java .io .InputStream ;
15+ import java .nio .file .Files ;
1316import org .springframework .core .io .ResourceLoader ;
1417import org .springframework .stereotype .Service ;
1518
1619import com .google .gson .JsonObject ;
20+ import com .google .gson .JsonArray ;
1721
1822import io .openvidu .loadtest .config .LoadTestConfig ;
1923import io .openvidu .loadtest .utils .CustomHttpClient ;
2024import io .openvidu .loadtest .utils .JsonUtils ;
2125
2226/**
23- * @author Carlos Santos
27+ * @author Carlos Santos & Iván Chicano
2428 *
2529 */
2630
2731@ Service
2832public class KibanaClient {
2933
3034 private static final String API_IMPORT_OBJECTS = "/api/saved_objects/_import?overwrite=true" ;
31- private static final String API_FIND_DASHBOARD = "/api/saved_objects/_find?type=dashboard&search_fields=title&search= " ;
35+ private static final String API_EXPORT_SAVED_OBJECTS = "/api/saved_objects/_export " ;
3236 private static final String KIBANA_DASHBOARD_URL = "/app/kibana#/dashboard/" ;
3337 private static final String LOAD_TEST_DASHBOARD = "Load Test" ;
3438
39+ private static final String DASHBOARD_NOT_FOUND = "Kibana Load Test Dashboard is not found. You can import it manually to see the results." ;
40+
3541 private static final int HTTP_STATUS_OK = 200 ;
3642
3743 private static final Logger log = LoggerFactory .getLogger (KibanaClient .class );
@@ -58,7 +64,8 @@ public void importDashboards() {
5864 this .kibanaHost = loadTestConfig .getKibanaHost ().replaceAll ("/$" , "" );
5965 log .info ("Importing Kibana JSON file with saved objects from resources directory" );
6066 Resource resource = resourceLoader .getResource ("classpath:loadtest.ndjson" );
61- importSavedObjects (resource .getFile ());
67+ File file = resourceToFile (resource );
68+ importSavedObjects (file );
6269 } catch (Exception e ) {
6370 log .warn ("Can't import dashboard to Kibana at {}" , this .kibanaHost );
6471 log .error (e .getMessage ());
@@ -68,11 +75,23 @@ public void importDashboards() {
6875 log .warn ("Kibana Host parameter is empty. Dashboard won't be imported." );
6976 }
7077
78+ private File resourceToFile (Resource resource ) throws IOException {
79+ try {
80+ return resource .getFile ();
81+ } catch (Exception ex ) {
82+ try (InputStream is = resource .getInputStream ()) {
83+ File file = File .createTempFile ("loadtest" , ".ndjson" );
84+ Files .copy (is , file .toPath (), StandardCopyOption .REPLACE_EXISTING );
85+ file .deleteOnExit ();
86+ return file ;
87+ }
88+ }
89+ }
90+
7191 public String getDashboardUrl (String startTime , String endTime ) {
7292 if (this .loadTestConfig .isKibanaEstablished ()) {
73-
74- final String URL = this .loadTestConfig .getKibanaHost () + API_FIND_DASHBOARD
75- + LOAD_TEST_DASHBOARD .replaceAll ("\\ s+" , "%20" );
93+ // Use the Export API instead of the deprecated _find endpoint.
94+ final String URL = this .loadTestConfig .getKibanaHost () + API_EXPORT_SAVED_OBJECTS ;
7695 Map <String , String > headers = new HashMap <>();
7796
7897 String esUserName = loadTestConfig .getElasticsearchUserName ();
@@ -81,18 +100,20 @@ public String getDashboardUrl(String startTime, String endTime) {
81100 if (securityEnabled ) {
82101 headers .put ("Authorization" , getBasicAuth (esUserName , esPassword ));
83102 }
103+ headers .put ("kbn-xsrf" , "true" );
84104
85105 try {
86- HttpResponse <String > response = this .httpClient .sendGet (URL , headers );
106+ JsonObject body = new JsonObject ();
107+ body .addProperty ("type" , "dashboard" );
108+ body .addProperty ("search" , LOAD_TEST_DASHBOARD );
109+ JsonArray searchFields = new JsonArray ();
110+ searchFields .add ("title" );
111+ body .add ("search_fields" , searchFields );
87112
88- if ( response . statusCode () == HTTP_STATUS_OK ) {
113+ HttpResponse < String > response = this . httpClient . sendPost ( URL , body , null , headers );
89114
90- JsonObject jsonResponse = this .jsonUtils .getJson (response .body ());
91- JsonObject dashboard = jsonResponse .get ("saved_objects" ).getAsJsonArray ().get (0 ).getAsJsonObject ();
92- String dashboardId = dashboard .get ("id" ).getAsString ();
93-
94- return this .loadTestConfig .getKibanaHost () + KIBANA_DASHBOARD_URL + dashboardId
95- + "?_g=(time:(from:'" + startTime + "',to:'" + endTime + "'))" ;
115+ if (response .statusCode () == HTTP_STATUS_OK ) {
116+ return extractDashboardUrlFromResponse (response , startTime , endTime );
96117 }
97118 } catch (InterruptedException e ) {
98119 Thread .currentThread ().interrupt ();
@@ -104,8 +125,25 @@ public String getDashboardUrl(String startTime, String endTime) {
104125 }
105126 }
106127
107- return "Kibana Load Test Dashboard is not found. You can import it manually to see the results." ;
128+ return DASHBOARD_NOT_FOUND ;
129+
130+ }
108131
132+ private String extractDashboardUrlFromResponse (HttpResponse <String > response , String startTime , String endTime ) {
133+ // response is NDJSON (one JSON object per line). Parse first dashboard object.
134+ String [] lines = response .body ().split ("\\ r?\\ n" );
135+ for (String line : lines ) {
136+ if (line == null || line .trim ().isEmpty ()) {
137+ continue ;
138+ }
139+ JsonObject obj = this .jsonUtils .getJson (line );
140+ if (obj .has ("type" ) && "dashboard" .equals (obj .get ("type" ).getAsString ()) && obj .has ("id" )) {
141+ String dashboardId = obj .get ("id" ).getAsString ();
142+ return this .loadTestConfig .getKibanaHost () + KIBANA_DASHBOARD_URL + dashboardId
143+ + "?_g=(time:(from:'" + startTime + "',to:'" + endTime + "'))" ;
144+ }
145+ }
146+ return DASHBOARD_NOT_FOUND ;
109147 }
110148
111149 private void importSavedObjects (File file ) throws IOException {
0 commit comments