mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Ability to view spark job urls in each paragraph
This commit is contained in:
parent
7420f2df75
commit
f16422f297
21 changed files with 234 additions and 23 deletions
|
|
@ -42,6 +42,8 @@ import org.apache.spark.repl.SparkILoop;
|
|||
import org.apache.spark.scheduler.ActiveJob;
|
||||
import org.apache.spark.scheduler.DAGScheduler;
|
||||
import org.apache.spark.scheduler.Pool;
|
||||
import org.apache.spark.scheduler.SparkListenerApplicationEnd;
|
||||
import org.apache.spark.scheduler.SparkListenerJobStart;
|
||||
import org.apache.spark.sql.SQLContext;
|
||||
import org.apache.spark.ui.SparkUI;
|
||||
import org.apache.spark.ui.jobs.JobProgressListener;
|
||||
|
|
@ -57,6 +59,7 @@ import org.apache.zeppelin.interpreter.WrappedInterpreter;
|
|||
import org.apache.zeppelin.interpreter.util.InterpreterOutputStream;
|
||||
import org.apache.zeppelin.resource.ResourcePool;
|
||||
import org.apache.zeppelin.resource.WellKnownResourceName;
|
||||
import org.apache.zeppelin.interpreter.remote.RemoteEventClientWrapper;
|
||||
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
|
||||
import org.apache.zeppelin.scheduler.Scheduler;
|
||||
import org.apache.zeppelin.scheduler.SchedulerFactory;
|
||||
|
|
@ -112,7 +115,7 @@ public class SparkInterpreter extends Interpreter {
|
|||
|
||||
private InterpreterOutputStream out;
|
||||
private SparkDependencyResolver dep;
|
||||
private String sparkUrl;
|
||||
private static String sparkUrl;
|
||||
|
||||
/**
|
||||
* completer - org.apache.spark.repl.SparkJLineCompletion (scala 2.10)
|
||||
|
|
@ -156,7 +159,43 @@ public class SparkInterpreter extends Interpreter {
|
|||
}
|
||||
|
||||
static JobProgressListener setupListeners(SparkContext context) {
|
||||
JobProgressListener pl = new JobProgressListener(context.getConf());
|
||||
JobProgressListener pl = new JobProgressListener(context.getConf()) {
|
||||
@Override
|
||||
public synchronized void onJobStart(SparkListenerJobStart jobStart) {
|
||||
super.onJobStart(jobStart);
|
||||
int jobId = jobStart.jobId();
|
||||
String jobGroupId = jobStart.properties().getProperty("spark.jobGroup.id");
|
||||
String jobUrl = getJobUrl(jobId);
|
||||
String noteId = getNoteId(jobGroupId);
|
||||
String paragraphId = getParagraphId(jobGroupId);
|
||||
if (jobUrl != null && noteId != null && paragraphId != null) {
|
||||
RemoteEventClientWrapper eventClient = ZeppelinContext.getEventClient();
|
||||
Map<String, String> infos = new java.util.HashMap<>();
|
||||
infos.put("jobUrl", jobUrl);
|
||||
eventClient.onParaInfosReceived(noteId, paragraphId, infos);
|
||||
}
|
||||
}
|
||||
|
||||
private String getJobUrl(int jobId) {
|
||||
String jobUrl = null;
|
||||
if (sparkUrl != null) {
|
||||
jobUrl = sparkUrl + "/jobs/job?id=" + jobId;
|
||||
}
|
||||
return jobUrl;
|
||||
}
|
||||
|
||||
private String getNoteId(String jobgroupId) {
|
||||
int indexOf = jobgroupId.indexOf("-");
|
||||
int secondIndex = jobgroupId.indexOf("-", indexOf + 1);
|
||||
return jobgroupId.substring(indexOf + 1, secondIndex);
|
||||
}
|
||||
|
||||
private String getParagraphId(String jobgroupId) {
|
||||
int indexOf = jobgroupId.indexOf("-");
|
||||
int secondIndex = jobgroupId.indexOf("-", indexOf + 1);
|
||||
return jobgroupId.substring(secondIndex + 1, jobgroupId.length());
|
||||
}
|
||||
};
|
||||
try {
|
||||
Object listenerBus = context.getClass().getMethod("listenerBus").invoke(context);
|
||||
|
||||
|
|
@ -973,6 +1012,7 @@ public class SparkInterpreter extends Interpreter {
|
|||
infos.put("url", sparkUrl);
|
||||
logger.info("Sending metainfos to Zeppelin server: {}", infos.toString());
|
||||
if (ctx != null && ctx.getClient() != null) {
|
||||
getZeppelinContext().setEventClient(ctx.getClient());
|
||||
ctx.getClient().onMetaInfosReceived(infos);
|
||||
}
|
||||
}
|
||||
|
|
@ -1105,8 +1145,8 @@ public class SparkInterpreter extends Interpreter {
|
|||
return obj;
|
||||
}
|
||||
|
||||
String getJobGroup(InterpreterContext context){
|
||||
return "zeppelin-" + context.getParagraphId();
|
||||
String getJobGroup(InterpreterContext context) {
|
||||
return "zeppelin-" + context.getNoteId() + "-" + context.getParagraphId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -102,7 +102,12 @@ public class SparkRInterpreter extends Interpreter {
|
|||
@Override
|
||||
public InterpreterResult interpret(String lines, InterpreterContext interpreterContext) {
|
||||
|
||||
getSparkInterpreter().populateSparkWebUrl(interpreterContext);
|
||||
SparkInterpreter sparkInterpreter = getSparkInterpreter();
|
||||
sparkInterpreter.populateSparkWebUrl(interpreterContext);
|
||||
|
||||
String jobGroup = sparkInterpreter.getJobGroup(interpreterContext);
|
||||
sparkInterpreter.getSparkContext().setJobGroup(jobGroup, "Zeppelin", false);
|
||||
|
||||
String imageWidth = getProperty("zeppelin.R.image.width");
|
||||
|
||||
String[] sl = lines.split("\n");
|
||||
|
|
|
|||
|
|
@ -45,10 +45,6 @@ public class SparkSqlInterpreter extends Interpreter {
|
|||
Logger logger = LoggerFactory.getLogger(SparkSqlInterpreter.class);
|
||||
AtomicInteger num = new AtomicInteger(0);
|
||||
|
||||
private String getJobGroup(InterpreterContext context){
|
||||
return "zeppelin-" + context.getParagraphId();
|
||||
}
|
||||
|
||||
private int maxResult;
|
||||
|
||||
public SparkSqlInterpreter(Properties property) {
|
||||
|
|
@ -105,7 +101,7 @@ public class SparkSqlInterpreter extends Interpreter {
|
|||
sc.setLocalProperty("spark.scheduler.pool", null);
|
||||
}
|
||||
|
||||
sc.setJobGroup(getJobGroup(context), "Zeppelin", false);
|
||||
sc.setJobGroup(sparkInterpreter.getJobGroup(context), "Zeppelin", false);
|
||||
Object rdd = null;
|
||||
try {
|
||||
// method signature of sqlc.sql() is changed
|
||||
|
|
@ -134,10 +130,11 @@ public class SparkSqlInterpreter extends Interpreter {
|
|||
|
||||
@Override
|
||||
public void cancel(InterpreterContext context) {
|
||||
SQLContext sqlc = getSparkInterpreter().getSQLContext();
|
||||
SparkInterpreter sparkInterpreter = getSparkInterpreter();
|
||||
SQLContext sqlc = sparkInterpreter.getSQLContext();
|
||||
SparkContext sc = sqlc.sparkContext();
|
||||
|
||||
sc.cancelJobGroup(getJobGroup(context));
|
||||
sc.cancelJobGroup(sparkInterpreter.getJobGroup(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import org.apache.zeppelin.interpreter.InterpreterContextRunner;
|
|||
import org.apache.zeppelin.interpreter.InterpreterException;
|
||||
import org.apache.zeppelin.interpreter.InterpreterHookRegistry;
|
||||
import org.apache.zeppelin.interpreter.RemoteWorksController;
|
||||
import org.apache.zeppelin.interpreter.remote.RemoteEventClientWrapper;
|
||||
import org.apache.zeppelin.spark.dep.SparkDependencyResolver;
|
||||
import org.apache.zeppelin.resource.Resource;
|
||||
import org.apache.zeppelin.resource.ResourcePool;
|
||||
|
|
@ -61,6 +62,7 @@ public class ZeppelinContext {
|
|||
// Map interpreter class name (to be used by hook registry) from
|
||||
// given replName in parapgraph
|
||||
private static final Map<String, String> interpreterClassMap;
|
||||
private static RemoteEventClientWrapper eventClient;
|
||||
static {
|
||||
interpreterClassMap = new HashMap<>();
|
||||
interpreterClassMap.put("spark", "org.apache.zeppelin.spark.SparkInterpreter");
|
||||
|
|
@ -221,7 +223,8 @@ public class ZeppelinContext {
|
|||
Object df, int maxResult) {
|
||||
Object[] rows = null;
|
||||
Method take;
|
||||
String jobGroup = "zeppelin-" + interpreterContext.getParagraphId();
|
||||
String jobGroup = "zeppelin-" + interpreterContext.getNoteId() + "-"
|
||||
+ interpreterContext.getParagraphId();
|
||||
sc.setJobGroup(jobGroup, "Zeppelin", false);
|
||||
|
||||
try {
|
||||
|
|
@ -930,4 +933,21 @@ public class ZeppelinContext {
|
|||
return resourcePool.getAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event client
|
||||
*/
|
||||
@ZeppelinApi
|
||||
public static RemoteEventClientWrapper getEventClient() {
|
||||
return eventClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set event client
|
||||
*/
|
||||
@ZeppelinApi
|
||||
public void setEventClient(RemoteEventClientWrapper eventClient) {
|
||||
if (ZeppelinContext.eventClient == null) {
|
||||
ZeppelinContext.eventClient = eventClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.apache.zeppelin.interpreter.remote;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
@ -21,4 +22,13 @@ public class RemoteEventClient implements RemoteEventClientWrapper {
|
|||
client.onMetaInfosReceived(infos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParaInfosReceived(String noteId, String paragraphId, Map<String, String> infos) {
|
||||
Map<String, String> paraInfos = new HashMap<String, String>(infos);
|
||||
paraInfos.put("noteId", noteId);
|
||||
paraInfos.put("paraId", paragraphId);
|
||||
client.onParaInfosReceived(paraInfos);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,4 +12,7 @@ public interface RemoteEventClientWrapper {
|
|||
|
||||
public void onMetaInfosReceived(Map<String, String> infos);
|
||||
|
||||
public void onParaInfosReceived(String noteId, String paragraphId,
|
||||
Map<String, String> infos);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,6 +470,10 @@ public class RemoteInterpreterEventClient implements ResourcePoolConnector {
|
|||
gson.toJson(infos)));
|
||||
}
|
||||
|
||||
public void onParaInfosReceived(Map<String, String> infos) {
|
||||
sendEvent(new RemoteInterpreterEvent(RemoteInterpreterEventType.PARA_INFOS,
|
||||
gson.toJson(infos)));
|
||||
}
|
||||
/**
|
||||
* Wait for eventQueue becomes empty
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -243,10 +243,18 @@ public class RemoteInterpreterEventPoller extends Thread {
|
|||
Map<String, String> metaInfos = gson.fromJson(event.getData(),
|
||||
new TypeToken<Map<String, String>>() {
|
||||
}.getType());
|
||||
String id = interpreterGroup.getId();
|
||||
int indexOfColon = id.indexOf(":");
|
||||
String settingId = id.substring(0, indexOfColon);
|
||||
String settingId = getInterpreterSettingId();
|
||||
listener.onMetaInfosReceived(settingId, metaInfos);
|
||||
} else if (event.getType() == RemoteInterpreterEventType.PARA_INFOS) {
|
||||
Map<String, String> paraInfos = gson.fromJson(event.getData(),
|
||||
new TypeToken<Map<String, String>>() {
|
||||
}.getType());
|
||||
String noteId = paraInfos.get("noteId");
|
||||
String paraId = paraInfos.get("paraId");
|
||||
String settingId = getInterpreterSettingId();
|
||||
if (noteId != null && paraId != null && settingId != null) {
|
||||
listener.onParaInfosReceived(noteId, paraId, settingId, paraInfos);
|
||||
}
|
||||
}
|
||||
logger.debug("Event from remote process {}", event.getType());
|
||||
} catch (Exception e) {
|
||||
|
|
@ -334,6 +342,12 @@ public class RemoteInterpreterEventPoller extends Thread {
|
|||
}
|
||||
}
|
||||
|
||||
private String getInterpreterSettingId() {
|
||||
String id = interpreterGroup.getId();
|
||||
int indexOfColon = id.indexOf(":");
|
||||
return id.substring(0, indexOfColon);
|
||||
}
|
||||
|
||||
private void sendResourcePoolResponseGetAll(ResourceSet resourceSet) {
|
||||
Client client = null;
|
||||
boolean broken = false;
|
||||
|
|
|
|||
|
|
@ -40,4 +40,6 @@ public interface RemoteInterpreterProcessListener {
|
|||
public void onFinished(Object resultObject);
|
||||
public void onError();
|
||||
}
|
||||
public void onParaInfosReceived(String noteId, String paragraphId,
|
||||
String interpreterSettingId, Map<String, String> metaInfos);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ public enum RemoteInterpreterEventType implements org.apache.thrift.TEnum {
|
|||
APP_STATUS_UPDATE(12),
|
||||
META_INFOS(13),
|
||||
REMOTE_ZEPPELIN_SERVER_RESOURCE(14),
|
||||
RESOURCE_INVOKE_METHOD(15);
|
||||
RESOURCE_INVOKE_METHOD(15),
|
||||
PARA_INFOS(16);
|
||||
|
||||
private final int value;
|
||||
|
||||
|
|
@ -94,6 +95,8 @@ public enum RemoteInterpreterEventType implements org.apache.thrift.TEnum {
|
|||
return REMOTE_ZEPPELIN_SERVER_RESOURCE;
|
||||
case 15:
|
||||
return RESOURCE_INVOKE_METHOD;
|
||||
case 16:
|
||||
return PARA_INFOS;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ enum RemoteInterpreterEventType {
|
|||
APP_STATUS_UPDATE = 12,
|
||||
META_INFOS = 13,
|
||||
REMOTE_ZEPPELIN_SERVER_RESOURCE = 14,
|
||||
RESOURCE_INVOKE_METHOD = 15
|
||||
RESOURCE_INVOKE_METHOD = 15,
|
||||
PARA_INFOS = 16
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -182,4 +182,10 @@ public class RemoteInterpreterOutputTestStream implements RemoteInterpreterProce
|
|||
public void onRemoteRunParagraph(String noteId, String ParagraphID) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParaInfosReceived(String noteId, String paragraphId,
|
||||
String interpreterSettingId, Map<String, String> metaInfos) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,6 +355,10 @@ public class RemoteSchedulerTest implements RemoteInterpreterProcessListener {
|
|||
|
||||
@Override
|
||||
public void onRemoteRunParagraph(String noteId, String PsaragraphID) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParaInfosReceived(String noteId, String paragraphId,
|
||||
String interpreterSettingId, Map<String, String> metaInfos) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import org.apache.zeppelin.interpreter.InterpreterSetting;
|
|||
import org.apache.zeppelin.rest.message.NewInterpreterSettingRequest;
|
||||
import org.apache.zeppelin.rest.message.UpdateInterpreterSettingRequest;
|
||||
import org.apache.zeppelin.server.JsonResponse;
|
||||
import org.apache.zeppelin.socket.NotebookServer;
|
||||
|
||||
/**
|
||||
* Interpreter Rest API
|
||||
|
|
@ -61,14 +62,17 @@ public class InterpreterRestApi {
|
|||
private static final Logger logger = LoggerFactory.getLogger(InterpreterRestApi.class);
|
||||
|
||||
private InterpreterFactory interpreterFactory;
|
||||
private NotebookServer notebookServer;
|
||||
|
||||
Gson gson = new Gson();
|
||||
|
||||
public InterpreterRestApi() {
|
||||
}
|
||||
|
||||
public InterpreterRestApi(InterpreterFactory interpreterFactory) {
|
||||
public InterpreterRestApi(InterpreterFactory interpreterFactory,
|
||||
NotebookServer notebookWsServer) {
|
||||
this.interpreterFactory = interpreterFactory;
|
||||
this.notebookServer = notebookWsServer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -179,18 +183,20 @@ public class InterpreterRestApi {
|
|||
@ZeppelinApi
|
||||
public Response restartSetting(String message, @PathParam("settingId") String settingId) {
|
||||
logger.info("Restart interpreterSetting {}, msg={}", settingId, message);
|
||||
|
||||
InterpreterSetting setting = interpreterFactory.get(settingId);
|
||||
try {
|
||||
RestartInterpreterRequest request = gson.fromJson(message, RestartInterpreterRequest.class);
|
||||
|
||||
String noteId = request == null ? null : request.getNoteId();
|
||||
interpreterFactory.restart(settingId, noteId, SecurityUtils.getPrincipal());
|
||||
notebookServer.clearParagraphRuntimeInfo(setting);
|
||||
|
||||
} catch (InterpreterException e) {
|
||||
logger.error("Exception in InterpreterRestApi while restartSetting ", e);
|
||||
return new JsonResponse<>(Status.NOT_FOUND, e.getMessage(), ExceptionUtils.getStackTrace(e))
|
||||
.build();
|
||||
}
|
||||
InterpreterSetting setting = interpreterFactory.get(settingId);
|
||||
if (setting == null) {
|
||||
return new JsonResponse<>(Status.NOT_FOUND, "", settingId).build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ public class ZeppelinServer extends Application {
|
|||
HeliumRestApi heliumApi = new HeliumRestApi(helium, notebook);
|
||||
singletons.add(heliumApi);
|
||||
|
||||
InterpreterRestApi interpreterApi = new InterpreterRestApi(replFactory);
|
||||
InterpreterRestApi interpreterApi = new InterpreterRestApi(replFactory, notebookWsServer);
|
||||
singletons.add(interpreterApi);
|
||||
|
||||
CredentialRestApi credentialApi = new CredentialRestApi(credentials);
|
||||
|
|
|
|||
|
|
@ -2314,4 +2314,43 @@ public class NotebookServer extends WebSocketServlet
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParaInfosReceived(String noteId, String paragraphId,
|
||||
String interpreterSettingId, Map<String, String> metaInfos) {
|
||||
Note note = notebook().getNote(noteId);
|
||||
if (note != null) {
|
||||
Paragraph paragraph = note.getParagraph(paragraphId);
|
||||
if (paragraph != null) {
|
||||
InterpreterSetting setting = notebook().getInterpreterFactory()
|
||||
.get(interpreterSettingId);
|
||||
setting.addNoteToPara(noteId, paragraphId);
|
||||
metaInfos.remove("noteId");
|
||||
metaInfos.remove("paraId");
|
||||
paragraph.updateRuntimeInfos(metaInfos);
|
||||
broadcast(note.getId(), new Message(OP.PARAGRAPH).put("paragraph", paragraph));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearParagraphRuntimeInfo(InterpreterSetting setting) {
|
||||
Map<String, Set<String>> noteIdAndParaMap = setting.getNoteIdAndParaMap();
|
||||
if (noteIdAndParaMap != null && !noteIdAndParaMap.isEmpty()) {
|
||||
for (String noteId : noteIdAndParaMap.keySet()) {
|
||||
Set<String> paraIdSet = noteIdAndParaMap.get(noteId);
|
||||
if (paraIdSet != null && !paraIdSet.isEmpty()) {
|
||||
for (String paraId : paraIdSet) {
|
||||
Note note = notebook().getNote(noteId);
|
||||
if (note != null) {
|
||||
Paragraph paragraph = note.getParagraph(paraId);
|
||||
paragraph.clearRuntimeInfo();
|
||||
if (paragraph != null) {
|
||||
broadcast(noteId, new Message(OP.PARAGRAPH).put("paragraph", paragraph));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,20 @@ limitations under the License.
|
|||
tooltip="Cancel (Ctrl+{{ (isMac ? 'Option' : 'Alt') }}+c)"
|
||||
ng-click="cancelParagraph(paragraph)"
|
||||
ng-show="paragraph.status=='RUNNING' || paragraph.status=='PENDING'"></span>
|
||||
<span ng-show="paragraph.runtimeInfos.jobUrl.length == 1">
|
||||
<a href="{{paragraph.runtimeInfos.jobUrl[0]}}" target="_blank"><span class="fa fa-tasks"></span> Spark job </a>
|
||||
</span>
|
||||
<span class="dropdown" ng-show="paragraph.runtimeInfos.jobUrl.length > 1">
|
||||
<span class="fa fa-tasks" style="cursor:pointer;color:#3071A9" tooltip-placement="top" tooltip="Run this paragraph (Shift+Enter)"
|
||||
data-toggle="dropdown"
|
||||
type="button"> Spark Jobs
|
||||
</span>
|
||||
<ul class="dropdown-menu" role="menu" style="width:200px;z-index:1002">
|
||||
<li ng-class="{'option-disabled': !noteOperationsAllowed()}" ng-repeat="url in paragraph.runtimeInfos.jobUrl">
|
||||
<a href="{{url}}" target="_blank"><span class="fa fa-external-link-square"></span> Jobs #{{$index}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
<span class="{{paragraph.config.editorHide ? 'icon-size-fullscreen' : 'icon-size-actual'}}" style="cursor:pointer" tooltip-placement="top"
|
||||
tooltip="{{(paragraph.config.editorHide ? 'Show' : 'Hide')}} editor (Ctrl+{{ (isMac ? 'Option' : 'Alt') }}+e)"
|
||||
ng-click="toggleEditor(paragraph)"></span>
|
||||
|
|
|
|||
|
|
@ -1083,7 +1083,8 @@ function ParagraphCtrl($scope, $rootScope, $route, $window, $routeParams, $locat
|
|||
isEmpty(newPara.results) !== isEmpty(oldPara.results) ||
|
||||
newPara.errorMessage !== oldPara.errorMessage ||
|
||||
!angular.equals(newPara.settings, oldPara.settings) ||
|
||||
!angular.equals(newPara.config, oldPara.config)))
|
||||
!angular.equals(newPara.config, oldPara.config) ||
|
||||
!angular.equals(newPara.runtimeInfos, oldPara.runtimeInfos)))
|
||||
}
|
||||
|
||||
$scope.updateAllScopeTexts = function(oldPara, newPara) {
|
||||
|
|
@ -1126,6 +1127,7 @@ function ParagraphCtrl($scope, $rootScope, $route, $window, $routeParams, $locat
|
|||
$scope.paragraph.results = newPara.results;
|
||||
}
|
||||
$scope.paragraph.settings = newPara.settings;
|
||||
$scope.paragraph.runtimeInfos = newPara.runtimeInfos;
|
||||
if ($scope.editor) {
|
||||
$scope.editor.setReadOnly($scope.isRunning(newPara));
|
||||
}
|
||||
|
|
@ -1139,7 +1141,6 @@ function ParagraphCtrl($scope, $rootScope, $route, $window, $routeParams, $locat
|
|||
$scope.paragraph.config = newPara.config;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.updateParagraph = function(oldPara, newPara, updateCallback) {
|
||||
// 1. get status, refreshed
|
||||
const statusChanged = (newPara.status !== oldPara.status);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
|
@ -47,6 +48,7 @@ public class InterpreterSetting {
|
|||
// always be null in case of InterpreterSettingRef
|
||||
private String group;
|
||||
private transient Map<String, String> infos;
|
||||
private transient Map<String, Set<String>> noteIdToParaIdsetMap;
|
||||
|
||||
/**
|
||||
* properties can be either Properties or Map<String, InterpreterProperty>
|
||||
|
|
@ -394,11 +396,28 @@ public class InterpreterSetting {
|
|||
return infos;
|
||||
}
|
||||
|
||||
<<<<<<< b1e06919fada4240f5440430f2c27c02e4e5626a
|
||||
public InterpreterRunner getInterpreterRunner() {
|
||||
return interpreterRunner;
|
||||
}
|
||||
|
||||
public void setInterpreterRunner(InterpreterRunner interpreterRunner) {
|
||||
this.interpreterRunner = interpreterRunner;
|
||||
=======
|
||||
public void addNoteToPara(String noteId, String paraId) {
|
||||
if(noteIdToParaIdsetMap == null) {
|
||||
noteIdToParaIdsetMap = new HashMap<>();
|
||||
}
|
||||
Set<String> paraIdSet = noteIdToParaIdsetMap.get(noteId);
|
||||
if(paraIdSet == null) {
|
||||
paraIdSet = new HashSet<>();
|
||||
noteIdToParaIdsetMap.put(noteId, paraIdSet);
|
||||
}
|
||||
paraIdSet.add(paraId);
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getNoteIdAndParaMap() {
|
||||
return noteIdToParaIdsetMap;
|
||||
>>>>>>> Ability to view spark job urls in each paragraph
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -480,6 +480,7 @@ public class Notebook implements NoteEventListener {
|
|||
if (p.getDateFinished() != null && lastUpdatedDate.before(p.getDateFinished())) {
|
||||
lastUpdatedDate = p.getDateFinished();
|
||||
}
|
||||
p.clearRuntimeInfo();
|
||||
}
|
||||
|
||||
Map<String, List<AngularObject>> savedObjects = note.getAngularObjects();
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ public class Paragraph extends Job implements Serializable, Cloneable {
|
|||
|
||||
// For backward compatibility of note.json format after ZEPPELIN-212
|
||||
Object result;
|
||||
private Map<String, Set<String>> runtimeInfos;
|
||||
|
||||
/**
|
||||
* Applicaiton states in this paragraph
|
||||
|
|
@ -676,4 +677,25 @@ public class Paragraph extends Job implements Serializable, Cloneable {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateRuntimeInfos(Map<String, String> infos) {
|
||||
if (this.runtimeInfos == null) {
|
||||
this.runtimeInfos = new HashMap<String, Set<String>>();
|
||||
}
|
||||
|
||||
if (infos != null) {
|
||||
for (String key : infos.keySet()) {
|
||||
Set<String> values = this.runtimeInfos.get(key);
|
||||
if (values == null) {
|
||||
values = new HashSet<>();
|
||||
this.runtimeInfos.put(key, values);
|
||||
}
|
||||
values.add(infos.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearRuntimeInfo() {
|
||||
this.runtimeInfos = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue