otel save

This commit is contained in:
Simon Larsen 2023-10-18 13:59:19 +01:00
parent d543757a7d
commit 352c9ffb8e
No known key found for this signature in database
GPG Key ID: AB45983AA9C81CDE
15 changed files with 362 additions and 16 deletions

View File

@ -1,4 +1,4 @@
import TableColumnType from '../Types/BaseDatabase/TableColumnType';
import TableColumnType from '../Types/AnalyticsDatabase/TableColumnType';
import AnalyticsTableColumn from '../Types/AnalyticsDatabase/TableColumn';
import BadDataException from '../Types/Exception/BadDataException';
import AnalyticsTableEngine from '../Types/AnalyticsDatabase/AnalyticsTableEngine';

View File

@ -0,0 +1,18 @@
import AnalyticsTableColumn from '../Types/AnalyticsDatabase/TableColumn';
export default class NestedModel {
private _nestedColumnns: Array<AnalyticsTableColumn> = [];
public get nestedColumnns(): Array<AnalyticsTableColumn> {
return this._nestedColumnns;
}
public set nestedColumnns(v: Array<AnalyticsTableColumn>) {
this._nestedColumnns = v;
}
public constructor(data: {
nestedColumns: Array<AnalyticsTableColumn>
}) {
this.nestedColumnns = data.nestedColumns;
}
}

View File

@ -21,7 +21,7 @@ import Email from '../Types/Email';
import Phone from '../Types/Phone';
import PositiveNumber from '../Types/PositiveNumber';
import Route from '../Types/API/Route';
import TableColumnType from '../Types/BaseDatabase/TableColumnType';
import TableColumnType from '../Types/Database/TableColumnType';
import Permission, {
instanceOfUserTenantAccessPermission,
PermissionHelper,

View File

@ -4,7 +4,7 @@ import ColumnLength from '../Types/Database/ColumnLength';
import ColumnType from '../Types/Database/ColumnType';
import SlugifyColumn from '../Types/Database/SlugifyColumn';
import TableColumn from '../Types/Database/TableColumn';
import TableColumnType from '../Types/BaseDatabase/TableColumnType';
import TableColumnType from '../Types/Database/TableColumnType';
import MimeType from '../Types/File/MimeType';
import ObjectID from '../Types/ObjectID';
import Permission from '../Types/Permission';

View File

@ -1,7 +1,9 @@
import { ColumnAccessControl } from '../BaseDatabase/AccessControl';
import ColumnBillingAccessControl from '../BaseDatabase/ColumnBillingAccessControl';
import TableColumnType from '../BaseDatabase/TableColumnType';
import TableColumnType from '../AnalyticsDatabase/TableColumnType';
import { JSONValue } from '../JSON';
import NestedModel from '../../AnalyticsModels/NestedModel';
export default class AnalyticsTableColumn {
private _key: string = 'id';
@ -45,7 +47,7 @@ export default class AnalyticsTableColumn {
this._isTenantId = v;
}
private _type: TableColumnType = TableColumnType.ShortText;
private _type: TableColumnType = TableColumnType.Text;
public get type(): TableColumnType {
return this._type;
}
@ -105,6 +107,7 @@ export default class AnalyticsTableColumn {
public constructor(data: {
key: string;
nestedModel?: NestedModel | undefined;
title: string;
description: string;
required: boolean;
@ -118,6 +121,11 @@ export default class AnalyticsTableColumn {
| (() => Date | string | number | boolean)
| undefined;
}) {
if(data.type === TableColumnType.NestedModel && !data.nestedModel){
throw new Error('NestedModel is required when type is NestedModel');
}
this.accessControl = data.accessControl;
this.key = data.key;
this.title = data.title;

View File

@ -0,0 +1,13 @@
enum ColumnType {
ObjectID = 'Object ID',
Date = 'Date',
Boolean = 'Boolean',
Number = 'Number',
Text = 'Text',
NestedModel = 'Nested',
JSON = 'JSON',
}
export default ColumnType;

View File

@ -1,4 +1,4 @@
import TableColumnType from '../BaseDatabase/TableColumnType';
import TableColumnType from './TableColumnType';
enum ColumnLength {
Version = 30,

View File

@ -2,7 +2,7 @@ import 'reflect-metadata';
import BaseModel from '../../Models/BaseModel';
import Dictionary from '../Dictionary';
import { ReflectionMetadataType } from '../Reflection';
import TableColumnType from '../BaseDatabase/TableColumnType';
import TableColumnType from './TableColumnType';
const tableColumn: Symbol = Symbol('TableColumn');

View File

@ -4,7 +4,7 @@ import OneUptimeDate from './Date';
import BaseModel from '../Models/BaseModel';
import { JSONArray, JSONObject, JSONValue, ObjectType } from './JSON';
import { TableColumnMetadata } from '../Types/Database/TableColumn';
import TableColumnType from './BaseDatabase/TableColumnType';
import TableColumnType from './Database/TableColumnType';
import SerializableObject from './SerializableObject';
import SerializableObjectDictionary from './SerializableObjectDictionary';
import JSON5 from 'json5';

View File

@ -55,7 +55,7 @@ router.use(
);
router.post(
'/otel/*',
'/otel/v1/traces',
async (
req: ExpressRequest,
res: ExpressResponse,
@ -73,4 +73,46 @@ router.post(
}
);
router.post(
'/otel/v1/metrics',
async (
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction
): Promise<void> => {
try {
logger.info('OTel Ingestor API called');
logger.info(req.body);
return Response.sendEmptyResponse(req, res);
} catch (err) {
return next(err);
}
}
);
router.post(
'/otel/v1/logs',
async (
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction
): Promise<void> => {
try {
logger.info('OTel Ingestor API called');
logger.info(req.body);
return Response.sendEmptyResponse(req, res);
} catch (err) {
return next(err);
}
}
);
export default router;

View File

@ -1,13 +1,34 @@
/**
* CREATE TABLE opentelemetry_logs
(
trace_id String,
span_id String,
name String,
time DateTime('UTC'),
body String,
attributes Nested
(
key String,
value String
),
flags Int32,
severity_number Int32,
severity_text String
) ENGINE = MergeTree()
ORDER BY (trace_id, span_id);
*/
import AnalyticsBaseModel from 'Common/AnalyticsModels/BaseModel';
import AnalyticsTableColumn from 'Common/Types/AnalyticsDatabase/TableColumn';
import TableColumnType from 'Common/Types/BaseDatabase/TableColumnType';
import TableColumnType from 'Common/Types/AnalyticsDatabase/TableColumnType';
import AnalyticsTableEngine from 'Common/Types/AnalyticsDatabase/AnalyticsTableEngine';
import ObjectID from 'Common/Types/ObjectID';
export default class Log extends AnalyticsBaseModel {
public constructor() {
super({
tableName: 'Logs',
tableName: 'Log',
tableEngine: AnalyticsTableEngine.MergeTree,
singularName: 'Log',
pluralName: 'Logs',
@ -21,9 +42,9 @@ export default class Log extends AnalyticsBaseModel {
}),
new AnalyticsTableColumn({
key: 'sourceId',
title: 'Source ID',
description: 'ID of the Log Source',
key: 'serviceId',
title: 'Service ID',
description: 'ID of the Service which created the log',
required: true,
type: TableColumnType.ObjectID,
}),
@ -33,7 +54,7 @@ export default class Log extends AnalyticsBaseModel {
title: 'Log Message',
description: 'Log message',
required: true,
type: TableColumnType.VeryLongText,
type: TableColumnType.Text,
}),
new AnalyticsTableColumn({
@ -49,7 +70,7 @@ export default class Log extends AnalyticsBaseModel {
title: 'Severity',
description: 'Log Severity',
required: true,
type: TableColumnType.ShortText,
type: TableColumnType.Text,
}),
],
primaryKeys: ['projectId', 'sourceId', 'timestamp'],

View File

@ -0,0 +1,27 @@
/**
*
* CREATE TABLE opentelemetry_metrics
(
name String,
description String,
unit String,
time DateTime('UTC'),
attributes Nested
(
key String,
value String
),
metric_values Nested
(
value Double,
labels Nested
(
key String,
value String
)
)
) ENGINE = MergeTree()
ORDER BY (name, time);
*
*/

View File

@ -0,0 +1,28 @@
import AnalyticsTableColumn from "Common/Types/AnalyticsDatabase/TableColumn";
import NestedModel from "Common/AnalyticsModels/NestedModel";
import TableColumnType from "Common/Types/AnalyticsDatabase/TableColumnType";
export default class KeyValueNestedModel extends NestedModel {
public constructor(){
super({
nestedColumns: [
new AnalyticsTableColumn({
key: 'key',
title: 'Key',
description: 'Key of the attribute',
required: true,
type: TableColumnType.Text,
}),
new AnalyticsTableColumn({
key: 'value',
title: 'Value',
description: 'Value of the attribute',
required: true,
type: TableColumnType.Text,
}),
]
})
}
}

View File

@ -0,0 +1,189 @@
/**
*
*
* CREATE TABLE opentelemetry_spans
(
trace_id String,
span_id String,
trace_state String,
parent_span_id String,
name String,
kind Int32,
start_time DateTime('UTC'),
end_time DateTime('UTC'),
attributes Nested
(
key String,
value String
),
events Nested
(
time DateTime('UTC'),
name String,
attributes Nested
(
key String,
value String
)
),
links Nested
(
trace_id String,
span_id String,
trace_state String,
attributes Nested
(
key String,
value String
)
),
status_code Int32,
status_message String
) ENGINE = MergeTree()
ORDER BY (trace_id, span_id);
*/
import AnalyticsBaseModel from 'Common/AnalyticsModels/BaseModel';
import AnalyticsTableColumn from 'Common/Types/AnalyticsDatabase/TableColumn';
import TableColumnType from 'Common/Types/AnalyticsDatabase/TableColumnType';
import AnalyticsTableEngine from 'Common/Types/AnalyticsDatabase/AnalyticsTableEngine';
import ObjectID from 'Common/Types/ObjectID';
import KeyValueNestedModel from './NestedModels/KeyValueNestedModel';
export default class Span extends AnalyticsBaseModel {
public constructor() {
super({
tableName: 'Span',
tableEngine: AnalyticsTableEngine.MergeTree,
singularName: 'Span',
pluralName: 'Spans',
tableColumns: [
new AnalyticsTableColumn({
key: 'projectId',
title: 'Project ID',
description: 'ID of project',
required: true,
type: TableColumnType.ObjectID,
}),
new AnalyticsTableColumn({
key: 'serviceId',
title: 'Service ID',
description: 'ID of the Service which created the log',
required: true,
type: TableColumnType.ObjectID,
}),
new AnalyticsTableColumn({
key: 'startTime',
title: 'Start Time',
description: 'When did the span start?',
required: true,
type: TableColumnType.Date,
}),
new AnalyticsTableColumn({
key: 'endTime',
title: 'End Time',
description: 'When did the span end?',
required: true,
type: TableColumnType.Date,
}),
new AnalyticsTableColumn({
key: 'traceId',
title: 'Trace ID',
description: 'ID of the trace',
required: true,
type: TableColumnType.Text,
}),
new AnalyticsTableColumn({
key: 'spanId',
title: 'Span ID',
description: 'ID of the span',
required: true,
type: TableColumnType.Text,
}),
new AnalyticsTableColumn({
key: 'parentSpanId',
title: 'Parent Span ID',
description: 'ID of the parent span',
required: false,
type: TableColumnType.Text,
}),
new AnalyticsTableColumn({
key: 'traceState',
title: 'Trace State',
description: 'Trace State',
required: false,
type: TableColumnType.NestedModel,
nestedModel: new KeyValueNestedModel()
}),
new AnalyticsTableColumn({
key: 'attributes',
title: 'Attributes',
description: 'Attributes',
required: false,
type: TableColumnType.NestedModel,
nestedModel: new KeyValueNestedModel()
}),
],
primaryKeys: ['projectId', 'sourceId', 'timestamp'],
});
}
public get severity(): string | undefined {
return this.getColumnValue('severity') as string | undefined;
}
public set severity(v: string | undefined) {
this.setColumnValue('severity', v);
}
public get timestamp(): Date | undefined {
return this.getColumnValue('timestamp') as Date | undefined;
}
public set timestamp(v: Date | undefined) {
this.setColumnValue('timestamp', v);
}
public get log(): string | undefined {
return this.getColumnValue('log') as string | undefined;
}
public set log(v: string | undefined) {
this.setColumnValue('log', v);
}
public get sourceId(): ObjectID | undefined {
return this.getColumnValue('sourceId') as ObjectID | undefined;
}
public set sourceId(v: ObjectID | undefined) {
this.setColumnValue('sourceId', v);
}
public get projectId(): ObjectID | undefined {
return this.getColumnValue('projectId') as ObjectID | undefined;
}
public set projectId(v: ObjectID | undefined) {
this.setColumnValue('projectId', v);
}
public get message(): string | undefined {
return this.getColumnValue('message') as string | undefined;
}
public set message(v: string | undefined) {
this.setColumnValue('message', v);
}
}