Skip to content

Commit

Permalink
Merge pull request #616 from traPtitech/fix/several-bugs
Browse files Browse the repository at this point in the history
fix loki stream and optimize
  • Loading branch information
motoki317 authored Jun 14, 2023
2 parents 4a179a1 + 63858f6 commit 643da24
Show file tree
Hide file tree
Showing 12 changed files with 483 additions and 977 deletions.
19 changes: 1 addition & 18 deletions api/proto/neoshowcase/protobuf/gateway.proto
Original file line number Diff line number Diff line change
Expand Up @@ -306,26 +306,11 @@ message ArtifactContent {
bytes content = 2;
}

message GetOutputRequest {
string application_id = 1;
// Leave empty to default to now
google.protobuf.Timestamp before = 2;
}

message ApplicationOutput {
google.protobuf.Timestamp time = 1;
string log = 2;
}

message GetOutputResponse {
repeated ApplicationOutput outputs = 1;
}

message GetOutputStreamRequest {
string application_id = 1;
google.protobuf.Timestamp after = 2;
}

message Build {
enum BuildStatus {
QUEUED = 0;
Expand Down Expand Up @@ -457,10 +442,8 @@ service APIService {
rpc SetEnvVar(SetApplicationEnvVarRequest) returns (google.protobuf.Empty);
// DeleteEnvVar アプリの環境変数を削除します システムによって設定された環境変数は削除できません
rpc DeleteEnvVar(DeleteApplicationEnvVarRequest) returns (google.protobuf.Empty);
// GetOutput アプリの出力を取得します
rpc GetOutput(GetOutputRequest) returns (GetOutputResponse);
// GetOutputStream アプリの出力をストリーム形式で取得します
rpc GetOutputStream(GetOutputStreamRequest) returns (stream ApplicationOutput);
rpc GetOutputStream(ApplicationIdRequest) returns (stream ApplicationOutput);
// StartApplication アプリを起動します 起動中の場合は再起動します
rpc StartApplication(ApplicationIdRequest) returns (google.protobuf.Empty);
// StopApplication アプリをシャットダウンします
Expand Down
15 changes: 2 additions & 13 deletions dashboard/src/api/neoshowcase/protobuf/gateway_connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// @ts-nocheck

import { Empty, MethodKind } from "@bufbuild/protobuf";
import { Application, ApplicationEnvVars, ApplicationIdRequest, ApplicationOutput, ArtifactContent, ArtifactIdRequest, AvailableDomains, AvailablePorts, Build, BuildIdRequest, BuildLog, CreateApplicationRequest, CreateRepositoryRequest, CreateUserKeyRequest, DeleteApplicationEnvVarRequest, DeleteUserKeyRequest, GenerateKeyPairResponse, GetApplicationsRequest, GetApplicationsResponse, GetBuildsResponse, GetOutputRequest, GetOutputResponse, GetOutputStreamRequest, GetRepositoriesRequest, GetRepositoriesResponse, GetSystemPublicKeyResponse, GetUserKeysResponse, GetUsersResponse, Repository, RepositoryIdRequest, RetryCommitBuildRequest, SetApplicationEnvVarRequest, SSHInfo, UpdateApplicationRequest, UpdateRepositoryRequest, User, UserKey } from "./gateway_pb.js";
import { Application, ApplicationEnvVars, ApplicationIdRequest, ApplicationOutput, ArtifactContent, ArtifactIdRequest, AvailableDomains, AvailablePorts, Build, BuildIdRequest, BuildLog, CreateApplicationRequest, CreateRepositoryRequest, CreateUserKeyRequest, DeleteApplicationEnvVarRequest, DeleteUserKeyRequest, GenerateKeyPairResponse, GetApplicationsRequest, GetApplicationsResponse, GetBuildsResponse, GetRepositoriesRequest, GetRepositoriesResponse, GetSystemPublicKeyResponse, GetUserKeysResponse, GetUsersResponse, Repository, RepositoryIdRequest, RetryCommitBuildRequest, SetApplicationEnvVarRequest, SSHInfo, UpdateApplicationRequest, UpdateRepositoryRequest, User, UserKey } from "./gateway_pb.js";

/**
* General / System
Expand Down Expand Up @@ -278,25 +278,14 @@ export const APIService = {
O: Empty,
kind: MethodKind.Unary,
},
/**
* GetOutput アプリの出力を取得します
*
* @generated from rpc neoshowcase.protobuf.APIService.GetOutput
*/
getOutput: {
name: "GetOutput",
I: GetOutputRequest,
O: GetOutputResponse,
kind: MethodKind.Unary,
},
/**
* GetOutputStream アプリの出力をストリーム形式で取得します
*
* @generated from rpc neoshowcase.protobuf.APIService.GetOutputStream
*/
getOutputStream: {
name: "GetOutputStream",
I: GetOutputStreamRequest,
I: ApplicationIdRequest,
O: ApplicationOutput,
kind: MethodKind.ServerStreaming,
},
Expand Down
125 changes: 0 additions & 125 deletions dashboard/src/api/neoshowcase/protobuf/gateway_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2334,51 +2334,6 @@ export class ArtifactContent extends Message<ArtifactContent> {
}
}

/**
* @generated from message neoshowcase.protobuf.GetOutputRequest
*/
export class GetOutputRequest extends Message<GetOutputRequest> {
/**
* @generated from field: string application_id = 1;
*/
applicationId = "";

/**
* Leave empty to default to now
*
* @generated from field: google.protobuf.Timestamp before = 2;
*/
before?: Timestamp;

constructor(data?: PartialMessage<GetOutputRequest>) {
super();
proto3.util.initPartial(data, this);
}

static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "neoshowcase.protobuf.GetOutputRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "application_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "before", kind: "message", T: Timestamp },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetOutputRequest {
return new GetOutputRequest().fromBinary(bytes, options);
}

static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetOutputRequest {
return new GetOutputRequest().fromJson(jsonValue, options);
}

static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetOutputRequest {
return new GetOutputRequest().fromJsonString(jsonString, options);
}

static equals(a: GetOutputRequest | PlainMessage<GetOutputRequest> | undefined, b: GetOutputRequest | PlainMessage<GetOutputRequest> | undefined): boolean {
return proto3.util.equals(GetOutputRequest, a, b);
}
}

/**
* @generated from message neoshowcase.protobuf.ApplicationOutput
*/
Expand Down Expand Up @@ -2422,86 +2377,6 @@ export class ApplicationOutput extends Message<ApplicationOutput> {
}
}

/**
* @generated from message neoshowcase.protobuf.GetOutputResponse
*/
export class GetOutputResponse extends Message<GetOutputResponse> {
/**
* @generated from field: repeated neoshowcase.protobuf.ApplicationOutput outputs = 1;
*/
outputs: ApplicationOutput[] = [];

constructor(data?: PartialMessage<GetOutputResponse>) {
super();
proto3.util.initPartial(data, this);
}

static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "neoshowcase.protobuf.GetOutputResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "outputs", kind: "message", T: ApplicationOutput, repeated: true },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetOutputResponse {
return new GetOutputResponse().fromBinary(bytes, options);
}

static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetOutputResponse {
return new GetOutputResponse().fromJson(jsonValue, options);
}

static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetOutputResponse {
return new GetOutputResponse().fromJsonString(jsonString, options);
}

static equals(a: GetOutputResponse | PlainMessage<GetOutputResponse> | undefined, b: GetOutputResponse | PlainMessage<GetOutputResponse> | undefined): boolean {
return proto3.util.equals(GetOutputResponse, a, b);
}
}

/**
* @generated from message neoshowcase.protobuf.GetOutputStreamRequest
*/
export class GetOutputStreamRequest extends Message<GetOutputStreamRequest> {
/**
* @generated from field: string application_id = 1;
*/
applicationId = "";

/**
* @generated from field: google.protobuf.Timestamp after = 2;
*/
after?: Timestamp;

constructor(data?: PartialMessage<GetOutputStreamRequest>) {
super();
proto3.util.initPartial(data, this);
}

static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "neoshowcase.protobuf.GetOutputStreamRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "application_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "after", kind: "message", T: Timestamp },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetOutputStreamRequest {
return new GetOutputStreamRequest().fromBinary(bytes, options);
}

static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetOutputStreamRequest {
return new GetOutputStreamRequest().fromJson(jsonValue, options);
}

static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetOutputStreamRequest {
return new GetOutputStreamRequest().fromJsonString(jsonString, options);
}

static equals(a: GetOutputStreamRequest | PlainMessage<GetOutputStreamRequest> | undefined, b: GetOutputStreamRequest | PlainMessage<GetOutputStreamRequest> | undefined): boolean {
return proto3.util.equals(GetOutputStreamRequest, a, b);
}
}

/**
* @generated from message neoshowcase.protobuf.Build
*/
Expand Down
18 changes: 4 additions & 14 deletions dashboard/src/pages/apps/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { A, useNavigate, useParams } from '@solidjs/router'
import { createEffect, createMemo, createResource, createSignal, For, onCleanup, Ref, Show } from 'solid-js'
import { createEffect, createResource, createSignal, For, onCleanup, Ref, Show } from 'solid-js'
import { client, handleAPIError, sshInfo } from '/@/libs/api'
import { Header } from '/@/components/Header'
import {
Expand All @@ -14,7 +14,6 @@ import { titleCase } from '/@/libs/casing'
import {
Application_ContainerState,
ApplicationConfig,
ApplicationOutput,
DeployType,
RuntimeConfig,
} from '/@/api/neoshowcase/protobuf/gateway_pb'
Expand All @@ -34,7 +33,6 @@ import {
} from '/@/components/Card'
import { LogContainer } from '/@/components/Log'
import { sleep } from '/@/libs/sleep'
import { Timestamp } from '@bufbuild/protobuf'
import { Code, ConnectError } from '@bufbuild/connect'
import useModal from '/@/libs/useModal'
import { ModalButtonsContainer, ModalContainer, ModalText } from '/@/components/Modal'
Expand Down Expand Up @@ -223,17 +221,10 @@ export default () => {
}
const { Modal: DeleteAppModal, open: openDeleteAppModal, close: closeDeleteAppModal } = useModal()

const now = new Date()
const [log] = createResource(
() => app()?.deployType === DeployType.RUNTIME && app()?.id,
(id) => client.getOutput({ applicationId: id, before: Timestamp.fromDate(now) }),
)
const reversedLog = createMemo(() => log() && ([...log().outputs].reverse() as ApplicationOutput[]))
const logStreamAbort = new AbortController()
const [logStream] = createResource(
() => app()?.deployType === DeployType.RUNTIME && app()?.id,
(id) =>
client.getOutputStream({ applicationId: id, after: Timestamp.fromDate(now) }, { signal: logStreamAbort.signal }),
(id) => client.getOutputStream({ id }, { signal: logStreamAbort.signal }),
)
const [streamedLog, setStreamedLog] = createSignal<string[]>([])
createEffect(() => {
Expand Down Expand Up @@ -267,7 +258,7 @@ export default () => {

let logRef: Ref<HTMLDivElement>
createEffect(() => {
if (!log() || !streamedLog()) return
if (!streamedLog()) return
const ref = logRef as HTMLDivElement
if (!ref) return
setTimeout(() => {
Expand Down Expand Up @@ -445,11 +436,10 @@ export default () => {
</CardItems>
</Card>
</Show>
<Show when={log()}>
<Show when={app().deployType === DeployType.RUNTIME}>
<Card>
<CardTitle>Container Log</CardTitle>
<LogContainer ref={logRef} overflowX='scroll'>
<For each={reversedLog()}>{(l) => <span>{l.log}</span>}</For>
<For each={streamedLog()}>{(line) => <span>{line}</span>}</For>
</LogContainer>
</Card>
Expand Down
3 changes: 1 addition & 2 deletions pkg/domain/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@ type ContainerLog struct {
}

type ContainerLogger interface {
Get(ctx context.Context, appID string, before time.Time) ([]*ContainerLog, error)
Stream(ctx context.Context, appID string, after time.Time) (<-chan *ContainerLog, error)
Stream(ctx context.Context, appID string) (<-chan *ContainerLog, error)
}
6 changes: 3 additions & 3 deletions pkg/infrastructure/backend/dockerimpl/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import (
)

const (
appLabel = "neoshowcase.trap.jp/app"
appIDLabel = "neoshowcase.trap.jp/app-id"
appRestartedAtLabel = "neoshowcase.trap.jp/restarted-at"
appLabel = "ns.trap.jp/app"
appIDLabel = "ns.trap.jp/app-id"
appRestartedAtLabel = "ns.trap.jp/restarted-at"
)

const (
Expand Down
26 changes: 2 additions & 24 deletions pkg/infrastructure/grpc/api_app_config_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package grpc

import (
"context"
"time"

"github.com/bufbuild/connect-go"
"google.golang.org/protobuf/types/known/emptypb"
Expand Down Expand Up @@ -44,29 +43,8 @@ func (s *APIService) DeleteEnvVar(ctx context.Context, req *connect.Request[pb.D
return res, nil
}

func (s *APIService) GetOutput(ctx context.Context, req *connect.Request[pb.GetOutputRequest]) (*connect.Response[pb.GetOutputResponse], error) {
msg := req.Msg
before := time.Now()
if req.Msg.Before != nil {
before = msg.Before.AsTime()
}
logs, err := s.svc.GetOutput(ctx, msg.ApplicationId, before)
if err != nil {
return nil, handleUseCaseError(err)
}
res := connect.NewResponse(&pb.GetOutputResponse{
Outputs: ds.Map(logs, pbconvert.ToPBApplicationOutput),
})
return res, nil
}

func (s *APIService) GetOutputStream(ctx context.Context, req *connect.Request[pb.GetOutputStreamRequest], st *connect.ServerStream[pb.ApplicationOutput]) error {
msg := req.Msg
after := time.Now()
if req.Msg.After != nil {
after = msg.After.AsTime()
}
err := s.svc.GetOutputStream(ctx, msg.ApplicationId, after, func(l *domain.ContainerLog) error {
func (s *APIService) GetOutputStream(ctx context.Context, req *connect.Request[pb.ApplicationIdRequest], st *connect.ServerStream[pb.ApplicationOutput]) error {
err := s.svc.GetOutputStream(ctx, req.Msg.Id, func(l *domain.ContainerLog) error {
return st.Send(pbconvert.ToPBApplicationOutput(l))
})
if err != nil {
Expand Down
Loading

0 comments on commit 643da24

Please sign in to comment.