<commit_before>/*-
 * -\-\-
 * Spotify Styx CLI
 * --
 * Copyright (C) 2016 Spotify AB
 * --
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * -/-/-
 */

package com.spotify.styx.cli;

import static com.spotify.styx.cli.CliUtil.colored;
import static com.spotify.styx.cli.CliUtil.coloredBright;
import static com.spotify.styx.cli.CliUtil.formatTimestamp;
import static com.spotify.styx.util.ParameterUtil.toParameter;
import static org.fusesource.jansi.Ansi.Color.BLACK;
import static org.fusesource.jansi.Ansi.Color.BLUE;
import static org.fusesource.jansi.Ansi.Color.CYAN;
import static org.fusesource.jansi.Ansi.Color.DEFAULT;
import static org.fusesource.jansi.Ansi.Color.GREEN;
import static org.fusesource.jansi.Ansi.Color.RED;
import static org.fusesource.jansi.Ansi.Color.YELLOW;

import com.google.common.collect.Iterables;
import com.spotify.styx.api.BackfillPayload;
import com.spotify.styx.api.RunStateDataPayload;
import com.spotify.styx.model.Backfill;
import com.spotify.styx.model.Resource;
import com.spotify.styx.model.Schedule;
import com.spotify.styx.model.Workflow;
import com.spotify.styx.model.WorkflowId;
import com.spotify.styx.model.WorkflowState;
import com.spotify.styx.model.data.EventInfo;
import com.spotify.styx.state.Message;
import com.spotify.styx.state.StateData;
import java.util.Collections;
import java.util.List;
import org.fusesource.jansi.Ansi;

class PrettyCliOutput implements CliOutput {

  private static final String BACKFILL_FORMAT = "%28s  %6s  %13s %12s  %-13s  %-13s  %-13s  %s  %s";

  @Override
  public void printStates(RunStateDataPayload runStateDataPayload) {
    System.out.println(String.format("  %-20s %-12s %-47s %-7s %s",
                                     "WORKFLOW INSTANCE",
                                     "STATE",
                                     "LAST EXECUTION ID",
                                     "TRIES",
                                     "PREVIOUS EXECUTION MESSAGE"));

    CliUtil.groupStates(runStateDataPayload.activeStates()).entrySet().forEach(entry -> {
      System.out.println();
      System.out.println(String.format("%s %s",
                                       colored(CYAN, entry.getKey().componentId()),
                                       colored(BLUE, entry.getKey().id())));
      entry.getValue().forEach(runStateData -> {
        final StateData stateData = runStateData.stateData();
        final Ansi ansiState = getAnsiForState(runStateData);

        final Message lastMessage = Iterables.getLast(
            stateData.messages(), Message.create(Message.MessageLevel.UNKNOWN, "No info"));
        final Ansi ansiMessage = colored(messageColor(lastMessage.level()),
                                         lastMessage.line());

        System.out.println(String.format("  %-20s %-20s %-47s %-7d %s",
                                         runStateData.workflowInstance().parameter(),
                                         ansiState,
                                         stateData.executionId().orElse("<no-execution-id>"),
                                         stateData.tries(),
                                         ansiMessage));
      });
    });
  }

  @Override
  public void printEvents(List<EventInfo> eventInfos) {
    final String formatString = "%-25s %-25s %s";
    System.out.println(String.format(formatString,
                                     "TIME",
                                     "EVENT",
                                     "DATA"));
    eventInfos.forEach(
        eventInfo -> System.out.println(String.format(formatString,
                                                      formatTimestamp(eventInfo.timestamp()),
                                                      eventInfo.name(),
                                                      eventInfo.info())));
  }

  @Override
  public void printBackfill(Backfill backfill) {
    final Schedule schedule = backfill.schedule();
    final WorkflowId workflowId = backfill.workflowId();

    System.out.println(String.format(BACKFILL_FORMAT,
                                     backfill.id(),
                                     backfill.halted(),
                                     backfill.allTriggered(),
                                     backfill.concurrency(),
                                     toParameter(schedule, backfill.start()),
                                     toParameter(schedule, backfill.end()),
                                     toParameter(schedule, backfill.nextTrigger()),
                                     workflowId.componentId(),
                                     workflowId.id()));
  }

  private void printBackfillHeader() {
    System.out.println(String.format(BACKFILL_FORMAT,
                                     "BACKFILL ID",
                                     "HALTED",
                                     "ALL TRIGGERED",
                                     "CONCURRENCY",
                                     "START (INCL)",
                                     "END (EXCL)",
                                     "NEXT TRIGGER",
                                     "COMPONENT",
                                     "WORKFLOW"));
  }

  @Override
  public void printBackfillPayload(BackfillPayload backfillPayload) {
    printBackfillHeader();

    printBackfill(backfillPayload.backfill());
    if (backfillPayload.statuses().isPresent()) {
      System.out.println();
      System.out.println();
      printStates(backfillPayload.statuses().get());
    }
  }

  @Override
  public void printBackfills(List<BackfillPayload> backfills) {
    printBackfillHeader();

    for (BackfillPayload backfillPayload : backfills) {
      printBackfill(backfillPayload.backfill());
      if (backfillPayload.statuses().isPresent()) {
        System.out.println();
        System.out.println();
        printStates(backfillPayload.statuses().get());
      }
    }
  }

  @Override
  public void printResources(List<Resource> resources) {
    final String format = "%50s %12s";
    System.out.println(String.format(format, "RESOURCE", "CONCURRENCY"));
    resources.forEach(resource -> System.out.println(
        String.format(format, resource.id(), resource.concurrency())));
  }

  @Override
  public void printMessage(String message) {
    System.out.println(message);
  }

  @Override
  public void printWorkflow(Workflow wf, WorkflowState state) {
    final String image = state.dockerImage().orElseGet(() ->
        wf.configuration().dockerImage().orElse(""));
    System.out.println("Component: " + wf.componentId());
    System.out.println(" Workflow: " + wf.id().id());
    System.out.println("  Enabled: " + state.enabled().map(Object::toString).orElse(""));
    System.out.println(" Schedule: " + wf.configuration().schedule());
    System.out.println("   Commit: " + state.commitSha().orElse(""));
    System.out.println("    Image: " + image);
    System.out.println("     Args: " + wf.configuration().dockerArgs().orElse(Collections.emptyList()));
    System.out.println("   Secret: " + wf.configuration().secret().map(s -> s.name() + ':' + s.mountPath()).orElse(""));
    System.out.println(" Svc Acct: " + wf.configuration().serviceAccount().orElse(""));
  }

  private Ansi getAnsiForState(RunStateDataPayload.RunStateData RunStateData) {
    final String state = RunStateData.state();
    switch (state) {
      case "WAITING":    return coloredBright(BLACK, state);
      case "NEW":        return coloredBright(BLACK, state);
      case "QUEUED":     return coloredBright(BLACK, state);
      case "PREPARE":    return colored(CYAN, state);
      case "SUBMITTING": return colored(CYAN, state);<commit_msg>align pretty with plain for workflow<commit_after>/*-
 * -\-\-
 * Spotify Styx CLI
 * --
 * Copyright (C) 2016 Spotify AB
 * --
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * -/-/-
 */

package com.spotify.styx.cli;

import static com.spotify.styx.cli.CliUtil.colored;
import static com.spotify.styx.cli.CliUtil.coloredBright;
import static com.spotify.styx.cli.CliUtil.formatTimestamp;
import static com.spotify.styx.util.ParameterUtil.toParameter;
import static org.fusesource.jansi.Ansi.Color.BLACK;
import static org.fusesource.jansi.Ansi.Color.BLUE;
import static org.fusesource.jansi.Ansi.Color.CYAN;
import static org.fusesource.jansi.Ansi.Color.DEFAULT;
import static org.fusesource.jansi.Ansi.Color.GREEN;
import static org.fusesource.jansi.Ansi.Color.RED;
import static org.fusesource.jansi.Ansi.Color.YELLOW;

import com.google.common.collect.Iterables;
import com.spotify.styx.api.BackfillPayload;
import com.spotify.styx.api.RunStateDataPayload;
import com.spotify.styx.model.Backfill;
import com.spotify.styx.model.Resource;
import com.spotify.styx.model.Schedule;
import com.spotify.styx.model.Workflow;
import com.spotify.styx.model.WorkflowId;
import com.spotify.styx.model.WorkflowState;
import com.spotify.styx.model.data.EventInfo;
import com.spotify.styx.state.Message;
import com.spotify.styx.state.StateData;
import java.util.Collections;
import java.util.List;
import org.fusesource.jansi.Ansi;

class PrettyCliOutput implements CliOutput {

  private static final String BACKFILL_FORMAT = "%28s  %6s  %13s %12s  %-13s  %-13s  %-13s  %s  %s";

  @Override
  public void printStates(RunStateDataPayload runStateDataPayload) {
    System.out.println(String.format("  %-20s %-12s %-47s %-7s %s",
                                     "WORKFLOW INSTANCE",
                                     "STATE",
                                     "LAST EXECUTION ID",
                                     "TRIES",
                                     "PREVIOUS EXECUTION MESSAGE"));

    CliUtil.groupStates(runStateDataPayload.activeStates()).entrySet().forEach(entry -> {
      System.out.println();
      System.out.println(String.format("%s %s",
                                       colored(CYAN, entry.getKey().componentId()),
                                       colored(BLUE, entry.getKey().id())));
      entry.getValue().forEach(runStateData -> {
        final StateData stateData = runStateData.stateData();
        final Ansi ansiState = getAnsiForState(runStateData);

        final Message lastMessage = Iterables.getLast(
            stateData.messages(), Message.create(Message.MessageLevel.UNKNOWN, "No info"));
        final Ansi ansiMessage = colored(messageColor(lastMessage.level()),
                                         lastMessage.line());

        System.out.println(String.format("  %-20s %-20s %-47s %-7d %s",
                                         runStateData.workflowInstance().parameter(),
                                         ansiState,
                                         stateData.executionId().orElse("<no-execution-id>"),
                                         stateData.tries(),
                                         ansiMessage));
      });
    });
  }

  @Override
  public void printEvents(List<EventInfo> eventInfos) {
    final String formatString = "%-25s %-25s %s";
    System.out.println(String.format(formatString,
                                     "TIME",
                                     "EVENT",
                                     "DATA"));
    eventInfos.forEach(
        eventInfo -> System.out.println(String.format(formatString,
                                                      formatTimestamp(eventInfo.timestamp()),
                                                      eventInfo.name(),
                                                      eventInfo.info())));
  }

  @Override
  public void printBackfill(Backfill backfill) {
    final Schedule schedule = backfill.schedule();
    final WorkflowId workflowId = backfill.workflowId();

    System.out.println(String.format(BACKFILL_FORMAT,
                                     backfill.id(),
                                     backfill.halted(),
                                     backfill.allTriggered(),
                                     backfill.concurrency(),
                                     toParameter(schedule, backfill.start()),
                                     toParameter(schedule, backfill.end()),
                                     toParameter(schedule, backfill.nextTrigger()),
                                     workflowId.componentId(),
                                     workflowId.id()));
  }

  private void printBackfillHeader() {
    System.out.println(String.format(BACKFILL_FORMAT,
                                     "BACKFILL ID",
                                     "HALTED",
                                     "ALL TRIGGERED",
                                     "CONCURRENCY",
                                     "START (INCL)",
                                     "END (EXCL)",
                                     "NEXT TRIGGER",
                                     "COMPONENT",
                                     "WORKFLOW"));
  }

  @Override
  public void printBackfillPayload(BackfillPayload backfillPayload) {
    printBackfillHeader();

    printBackfill(backfillPayload.backfill());
    if (backfillPayload.statuses().isPresent()) {
      System.out.println();
      System.out.println();
      printStates(backfillPayload.statuses().get());
    }
  }

  @Override
  public void printBackfills(List<BackfillPayload> backfills) {
    printBackfillHeader();

    for (BackfillPayload backfillPayload : backfills) {
      printBackfill(backfillPayload.backfill());
      if (backfillPayload.statuses().isPresent()) {
        System.out.println();
        System.out.println();
        printStates(backfillPayload.statuses().get());
      }
    }
  }

  @Override
  public void printResources(List<Resource> resources) {
    final String format = "%50s %12s";
    System.out.println(String.format(format, "RESOURCE", "CONCURRENCY"));
    resources.forEach(resource -> System.out.println(
        String.format(format, resource.id(), resource.concurrency())));
  }

  @Override
  public void printMessage(String message) {
    System.out.println(message);
  }

  @Override
  public void printWorkflow(Workflow wf, WorkflowState state) {
    final String image = state.dockerImage().orElseGet(() ->
        wf.configuration().dockerImage().orElse(""));
    System.out.println("Component: " + wf.componentId());
    System.out.println(" Workflow: " + wf.id().id());
    System.out.println(" Schedule: " + wf.configuration().schedule());
    System.out.println("   Offset: " + wf.configuration().offset().orElse(""));
    System.out.println("    Image: " + image);
    System.out.println("     Args: " + wf.configuration().dockerArgs().orElse(Collections.emptyList()));
    System.out.println("  TermLog: " + wf.configuration().dockerTerminationLogging());
    System.out.println("   Secret: " + wf.configuration().secret().map(s -> s.name() + ':' + s.mountPath()).orElse(""));
    System.out.println(" Svc Acct: " + wf.configuration().serviceAccount().orElse(""));
    System.out.println("Resources: " + wf.configuration().resources());
    System.out.println("   Commit: " + state.commitSha().orElse(""));
    System.out.println("  Enabled: " + state.enabled().map(Object::toString).orElse(""));
    System.out.println("     Trig: " + state.nextNaturalTrigger().map(Object::toString).orElse(""));
    System.out.println("Ofst Trig :" + state.nextNaturalOffsetTrigger().map(Object::toString).orElse(""));
  }

  private Ansi getAnsiForState(RunStateDataPayload.RunStateData RunStateData) {
    final String state = RunStateData.state();
    switch (state) {
      case "WAITING":    return coloredBright(BLACK, state);
      case "NEW":        return coloredBright(BLACK, state);
      case "QUEUED":     return coloredBright(BLACK, state);
      case "PREPARE":    return colored(CYAN, state);
      case "SUBMITTING": return colored(CYAN, state);
{'fraction_non_alphanumeric': 0.12117981520966596, 'fraction_numerical': 0.005093579720445392, 'mean_word_length': 2.05003612716763, 'pattern_counts': {'":': 10, '<': 11, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 96, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2560659', 'n_tokens_mistral': 4700, 'n_tokens_neox': 4485, 'n_words': 868}