private static ExecutionPoint snapshot(boolean fast) { ExecutionPoint result = new ExecutionPoint(); result.threadName = Thread.currentThread().getName(); result.stacktraceHolder = new Exception(); if (!fast) { result.mdc = CallContext.getCurrent().getMDC(); } return result; }
/** * Creates a new CallContext for the given thread. * <p> * Discards the current <tt>CallContext</tt>, if there was already one. * * @return the newly created CallContext, which is already attached to the current thread. */ public static CallContext initialize() { return initialize(true, getNodeName() + "/" + interactionCounter.getCount()); }
/** * Queues the given task to be called after roughly the number of seconds given here. * <p> * In contrast to {@link #callDelayed(String, long, Runnable)}, this will preserve the {@link CallContext} when * invoking the <tt>task</tt>. * </p> * * @param executor the executor to execute the task in. Use {@link Tasks#DEFAULT} is no other appropriate * pool * is available. * @param delayInSeconds the number to wait in seconds. Note that the delay can be a bit longer, depending on the * system load. * @param task the task to execute */ public void forkDelayed(@Nonnull String executor, long delayInSeconds, @Nonnull Runnable task) { CallContext currentContext = CallContext.getCurrent(); callDelayed(executor, delayInSeconds, () -> { CallContext backup = CallContext.getCurrent(); try { CallContext.setCurrent(currentContext); task.run(); } finally { CallContext.setCurrent(backup); } }); }
/** * Provides access to the <tt>TaskContext</tt> for the current thread. * <p> * This is boilerplate for {@code CallContext.getCurrent().get(TaskContext.class)} * * @return the task context for the current thread */ public static TaskContext get() { return CallContext.getCurrent().get(TaskContext.class); }
/** * Returns the currently active language as two-letter code. * * @return a two-letter code of the currently active language, as defined in * {@link sirius.kernel.async.CallContext#getLang()} */ @Nonnull public static String getCurrentLang() { return CallContext.getCurrent().getLang(); }
/** * Prepares the execution of this task while checking all preconditions. */ void prepare() { if (fork) { ctx = CallContext.getCurrent().fork(); } if (runnable == null) { throw new IllegalArgumentException("Please provide a runnable for me to execute!"); } }
private void fixMDC() { if (logger.isDebugEnabled() || Sirius.isDev() || Sirius.isStartedAsTest()) { CallContext callContext = CallContext.getCurrent(); MDC.put("flow", "|" + callContext.getWatch().elapsedMillis() + "ms"); } }
Optional<CallContext> cc = CallContext.getContext(thread.getKey().getId()); if (cc.isPresent()) { output.line("Mapped Diagnostic Context"); output.separator(); for (Tuple<String, String> e : cc.get().getMDC()) { output.apply("%-20s %59s", e.getFirst(), e.getSecond()); output.apply("Flow duration: %s", cc.get().getWatch().duration());
private static CallContext initialize(boolean install, String externalFlowId) { CallContext ctx = new CallContext(); ctx.addToMDC(MDC_FLOW, externalFlowId); interactionCounter.inc(); if (install) { setCurrent(ctx); } return ctx; }
/** * Returns the two-letter code of the fall back language. Provided via the {@link CallContext}. If the value is * empty, {@link NLS#getDefaultLanguage} is returned. * * @return the language code of the fallback language */ @Nonnull public static String getFallbackLanguage() { String fallback = CallContext.getCurrent().getFallbackLang(); if (Strings.isEmpty(fallback)) { return getDefaultLanguage(); } return fallback; }
@Override public void run() { try { Watch w = Watch.start(); try { if (ctx == null) { CallContext.initialize(); } else { CallContext.setCurrent(ctx); } TaskContext.get().setSystem(SYSTEM_ASYNC).setSubSystem(category).setJob(String.valueOf(jobNumber)); runnable.run(); promise.success(null); } finally { CallContext.detach(); durationAverage.addValue(w.elapsedMillis()); } } catch (Exception t) { Exceptions.handle(Tasks.LOG, t); promise.fail(t); } }
WaitingBlock(Runnable cmd) { this.cmd = cmd; this.waitline = System.currentTimeMillis() + 1000; this.context = CallContext.getCurrent(); }
/** * Forks and creates a sub context. * <p> * All instantiated sub contexts are forked, the MDC is re-initialized. * * @return a copy of the current call context including a fork of all available sub contexts. * @see SubContext#fork() */ public CallContext fork() { CallContext newCtx = initialize(false, getMDCValue(MDC_FLOW).asString()); newCtx.watch = watch; newCtx.addToMDC(MDC_PARENT, getMDCValue(TaskContext.MDC_SYSTEM).asString()); subContext.forEach((key, value) -> newCtx.subContext.put(key, value.fork())); newCtx.lang = lang; newCtx.lazyLanguageInstaller = lazyLanguageInstaller; newCtx.fallbackLang = fallbackLang; return newCtx; }
/** * Releases the given lock. * * @param lock the lock to release * @param force if <tt>true</tt>, the lock will even be released if it is held by another node. This is a very * dangerous operation and should only be used by maintenance and management tools like {@link * RedisCommand}. */ public void unlock(String lock, boolean force) { exec(() -> "Unlock: " + lock, redis -> { String key = PREFIX_LOCK + lock; String lockOwner = redis.get(key); if (force || Strings.areEqual(lockOwner, CallContext.getNodeName())) { redis.del(key); redis.del(key + SUFFIX_DATE); } else { if (lockOwner == null) { LOG.WARN("Not going to unlock '%s' for '%s' as it seems to be expired already", lock, CallContext.getNodeName()); } else { LOG.WARN("Not going to unlock '%s' for '%s' as it is currently held by '%s'", lock, CallContext.getNodeName(), lockOwner); } } }); } }
@Override public String toString() { StringBuilder sb = new StringBuilder(); for (Tuple<String, String> e : getMDC()) { sb.append(e.getFirst()); sb.append(": "); sb.append(e.getSecond()); sb.append("\n"); } return sb.toString(); } }
/** * Executes the action in its own executor */ public void execute() { CallContext.setCurrent(context); tasks.executor("index-delay").fork(cmd); } }
/** * Sets the <tt>Sub-System</tt> component of the <tt>System String</tt> * * @param subSystem the new sub system component to set * @return the task context itself for fluent method calls * @see #getSystemString() */ public TaskContext setSubSystem(String subSystem) { if (Strings.isEmpty(subSystem)) { this.subSystem = GENERIC; } else { this.subSystem = subSystem; } parent.addToMDC(MDC_SYSTEM, getSystemString()); return this; }
/** * Detaches this CallContext from the current thread */ public static void detach() { CallContext ctx = currentContext.get(); if (ctx != null) { ctx.detachContext(); } currentContext.set(null); contextMap.remove(Thread.currentThread().getId()); }
/** * Writes an API success entry to the log */ private void signalObjectSuccess(WebContext ctx) { log.log(ctx.getRequest().method().name(), ctx.getRequestedURI(), APILog.Result.OK, CallContext.getCurrent().getWatch()); }
/** * Creates a new XMLReader. * <p> * Use {@link #addHandler(String, NodeHandler)} tobind handlers to tags and then call one of the <tt>parse</tt> * methods to process the XML file. * <p> * To interrupt processing use {@link TaskContext#cancel()}. */ public XMLReader() { try { documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); taskContext = CallContext.getCurrent().get(TaskContext.class); } catch (ParserConfigurationException e) { throw Exceptions.handle(e); } }