Skip to content

Public JobLogs API v1 #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 189 additions & 0 deletions semaphore/logs.v1.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
syntax = "proto3";

package semaphore.logs.v1;

//
// The Logs API provides logs for an executed job.
//
// The logs can be fetched in two formats. The raw JSON_LINES format, or the
// processed PLAIN_TEXT format.
//
// The Log API is resticting the payload length size to 10000 log events and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this 10k events is our hard limit? This job has 17_769 events and "only" 4,2 MB.

// the total response size 64 megabytes. The response contains infomrmation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

infomrmation -> information`

// about the number of lines returned, and if the end of the stream has been
// reached.
//
// To fetch the full logs, you need to iterate till the end. Example for a log
// that has 1040 log lines:
//
// GetLogs(start_from: 0) # => Response { length: 1000, end_reached: false }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1k is page size? currently we are fetching 10k events at once.

// GetLogs(start_from: 1000) # => Response { length: 40, end_reached: true }
//
// ## The JSON_LINES format
//
// When the JSON_LINES lines format is requested, the GetLogsResponse.content
// contains raw JSON LINES that describe events that happened during the
// execution of the job.
//
// This format is suitable for machine consuption.
//
// Example:
//
// {"event":"job_started", "timestamp": 1577446866 }
// {"event":"cmd_started", "timestamp": 1577446866, "directive":"Exporting environment variables"}
// {"event":"cmd_finished", "timestamp": 1577446866, "directive":"Exporting environment variables","exit_code":0,"finished_at":"*","started_at":"*"}
// {"event":"cmd_started", "timestamp": 1577446866, "directive":"Injecting Files"}
// {"event":"cmd_finished", "timestamp": 1577446866, "directive":"Injecting Files","exit_code":0,"finished_at":"*","started_at":"*"}
// {"event":"cmd_started", "timestamp": 1577446866, "directive":"echo Hello World"}
// {"event":"cmd_output", "timestamp": 1577446866, "output":"Hello World\\n"}
// {"event":"cmd_finished", "timestamp": 1577446866, "directive":"echo Hello World","exit_code":0,"finished_at":"*","started_at":"*"}
// {"event":"cmd_started", "timestamp": 1577446866, "directive":"export SEMAPHORE_JOB_RESULT=passed"}
// {"event":"cmd_finished", "timestamp": 1577446866, "directive":"export SEMAPHORE_JOB_RESULT=passed","exit_code":0,"finished_at":"*","started_at":"*"}
// {"event":"job_finished", "timestamp": 1577446866, "result":"passed"}
//
// Every log event has at least two fields:
//
// - "event" - enum ("job_started", "cmd_started", "cmd_output", "cmd_finished", "job_finished")
// - "timestamp" - Unix timestamp that represents when the event happened
//
// The events can be one of the following:
//
// - "job_started" - Event represents the start of the job execution.
// - "job_finished" - Event represents the end of the job execution.
// - "cmd_started" - Event represents the start of the command execution.
// - "cmd_output" - Event represents an output of command. There are multiple command output events for one command.
// - "cmd_finished" - Event represents the end of the command execution.
//
// Additional fields for "job_finished":
//
// - "result" - final result of the job, enum ("passed", "failed", "stopped")
//
// Additional fields for "cmd_started":
//
// - "directive" - The command that is being executed.
//
// Additional fields for "cmd_started":
//
// - "output" - An output generated by the command.
//
// Additional fields for "cmd_finished":
//
// - "directive" - The command that was executed.
// - "exit_code" - A unix exit code. Range (0..255).
// - "started_at" - Unix timestamp when the command started.
// - "finished_at" - Unix timestamp when the command finished.
//
// ## The PLAIN_TEXT format
//
// When the PLAIN_TEXT format is requested, the GetLogsResponse.content contains
// the output of the job after all all the unix escape characters have been
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all all -> all

// processed.
//
// This format is suitable for human consuption.
//
// Example:
//
// Exporting environment variables
// Exporting TERM
// Exporting PAGER
// Exporting DISPLAY
// Exporting CI
// Exporting SEMAPHORE
// Exporting SEMAPHORE_PROJECT_NAME
// Exporting SEMAPHORE_PROJECT_ID
// Exporting SEMAPHORE_JOB_NAME
// Exporting SEMAPHORE_JOB_ID
// Exporting SEMAPHORE_AGENT_MACHINE_TYPE
// Exporting SEMAPHORE_AGENT_MACHINE_OS_IMAGE
// Exporting SEMAPHORE_AGENT_MACHINE_ENVIRONMENT_TYPE
// Exporting SEMAPHORE_ORGANIZATION_URL
// Exporting SEMAPHORE_ARTIFACT_TOKEN
// Exporting SSH_PRIVATE_KEY_PATH
// Exporting SEMAPHORE_CACHE_PRIVATE_KEY_PATH
// Exporting SEMAPHORE_CACHE_USERNAME
// Exporting SEMAPHORE_CACHE_URL
// Exporting SEMAPHORE_GIT_URL
// Exporting SEMAPHORE_GIT_DIR
// Exporting SEMAPHORE_GIT_SHA
// Exporting SEMAPHORE_GIT_REPO_SLUG
// Exporting SEMAPHORE_GIT_REF
// Exporting SEMAPHORE_GIT_COMMIT_RANGE
// Exporting SEMAPHORE_GIT_REF_TYPE
// Exporting SEMAPHORE_GIT_BRANCH
// Exporting SEMAPHORE_WORKFLOW_ID
// Exporting SEMAPHORE_WORKFLOW_NUMBER
// Exporting SEMAPHORE_PIPELINE_ARTEFACT_ID
// Exporting SEMAPHORE_PIPELINE_ID
// Exporting SEMAPHORE_PIPELINE_0_ARTEFACT_ID
// Exporting APP_ENV
// Exporting SEMAPHORE_JOB_COUNT
// Exporting SEMAPHORE_JOB_INDEX
// Injecting Files
// Injecting /home/semaphore/.ssh/semaphore_cache_key with file mode 0600
// Injecting .ssh/id_rsa with file mode 0600
// git clone https://github.com/semaphoreci/toolbox.git ~/.toolbox
// Cloning into '/home/semaphore/.toolbox'...
// remote: Enumerating objects: 15, done.[K
// remote: Counting objects: 6% (1/15)[K
// remote: Counting objects: 13% (2/15)[K
// remote: Counting objects: 100% (3/15)[K
// remote: Compressing objects: 90% (9/10)[K
// remote: Compressing objects: 100% (10/10)[K
// remote: Compressing objects: 100% (10/10), done.[K
// Receiving objects: 0% (1/1158)
// Receiving objects: 1% (12/1158)
// Receiving objects: 2% (24/1158)
// Receiving objects: 3% (35/1158)
// Receiving objects: 4% (47/1158)
// Receiving objects: 5% (58/1158)
// Receiving objects: 100% (1158/1158)
// Receiving objects: 100% (1158/1158), 246.87 KiB | 851.00 KiB/s, done.
// Resolving deltas: 0% (0/648)
// Resolving deltas: 1% (7/648)
// Resolving deltas: 4% (32/648)
// Resolving deltas: 6% (44/648)
// Resolving deltas: 9% (61/648)
// Resolving deltas: 10% (68/648)
// Resolving deltas: 11% (72/648)
// Resolving deltas: 100% (648/648), done.
// bash ~/.toolbox/install-toolbox
// source ~/.toolbox/toolbox
// echo 'source ~/.toolbox/toolbox' >> ~/.bash_profile
// if [ -f /etc/init.d/xvfb ]; then /etc/init.d/xvfb start; fi
// Starting virtual X frame buffer: Xvfb.
// eval `ssh-agent`
// Agent pid 1820
// echo 'eval $(ssh-agent) >/dev/null' >> ~/.bash_profile
// ssh-add /home/semaphore/.ssh/semaphore_cache_key
// checkout
// Performing shallow clone with depth: 50
// HEAD is now at dc58f94 Outer layer is innaccessible
// sleep 10
// export SEMAPHORE_JOB_RESULT=passed
//

service LogsApi {
rpc GetLogs(GetLogsRequest) returns (GetLogsResponse);
}

message GetLogsRequest {
string job_id = 1;
int64 start_from = 2;

enum Format {
JSON_LINES = 0;
PLAIN_TEXT = 1;
}

Format format = 3;
}

message GetLogsResponse {
string job_id = 1;

int64 start_from = 2;
int64 length = 3;
bool end_reached = 4;

string content = 5;
}
8 changes: 8 additions & 0 deletions semaphore/logs.v1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type: google.api.Service
config_version: 3

http:
rules:

- selector: semaphore.logs.v1.LogsApi.GetLogs
get: /api/v1/logs/{job_id}