@red-hat-developer-hub/backstage-plugin-orchestrator-backend-module-loki 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-orchestrator-backend-module-loki
|
|
2
2
|
|
|
3
|
+
## 1.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ccbf5f4: Fixes https://issues.redhat.com/browse/RHDHBUGS-2735. Adds the ability to pass an auth token to the lokistack query route
|
|
8
|
+
|
|
9
|
+
Also adds the ability to add custom Loki log pipeline filters
|
|
10
|
+
|
|
11
|
+
## 1.1.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [309547d]
|
|
16
|
+
- @red-hat-developer-hub/backstage-plugin-orchestrator-common@3.5.2
|
|
17
|
+
- @red-hat-developer-hub/backstage-plugin-orchestrator-node@1.1.2
|
|
18
|
+
|
|
3
19
|
## 1.1.1
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -20,6 +36,21 @@
|
|
|
20
36
|
- @red-hat-developer-hub/backstage-plugin-orchestrator-common@3.5.0
|
|
21
37
|
- @red-hat-developer-hub/backstage-plugin-orchestrator-node@1.1.0
|
|
22
38
|
|
|
39
|
+
## 1.0.3
|
|
40
|
+
|
|
41
|
+
### Patch Changes
|
|
42
|
+
|
|
43
|
+
- Updated dependencies [02a0552]
|
|
44
|
+
- @red-hat-developer-hub/backstage-plugin-orchestrator-node@1.0.2
|
|
45
|
+
|
|
46
|
+
## 1.0.2
|
|
47
|
+
|
|
48
|
+
### Patch Changes
|
|
49
|
+
|
|
50
|
+
- cb26604: Fixes https://issues.redhat.com/browse/RHDHBUGS-2735. Adds the ability to pass an auth token to the lokistack query route
|
|
51
|
+
|
|
52
|
+
Also adds the ability to add custom Loki log pipeline filters
|
|
53
|
+
|
|
23
54
|
## 1.0.1
|
|
24
55
|
|
|
25
56
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -13,15 +13,24 @@ orchestrator:
|
|
|
13
13
|
workflowLogProvider:
|
|
14
14
|
loki:
|
|
15
15
|
baseUrl: http://localhost:3100
|
|
16
|
+
token: secrettoken
|
|
17
|
+
# rejectUnauthorized: false
|
|
18
|
+
# logPipelineFilters:
|
|
19
|
+
# - '| filter1'
|
|
20
|
+
# - '|= filter2'
|
|
16
21
|
# logStreamSelectors:
|
|
17
22
|
# - label: 'app'
|
|
18
23
|
# value: '=~".+"'
|
|
19
24
|
```
|
|
20
25
|
|
|
21
|
-
The `baseUrl`
|
|
26
|
+
The `baseUrl` and `token` are required.
|
|
27
|
+
|
|
28
|
+
If you're baseURL is using a self-signed certificate, add the `rejectUnauthorized: false` parameter. Note: this should only be used in development.
|
|
22
29
|
|
|
23
30
|
Multiple Log Stream Selectors can be specified in the `logStreamSelectors` section. See the loki docs to learn more about log stream selectors and their values: https://grafana.com/docs/loki/latest/query/log_queries/#log-stream-selector
|
|
24
31
|
|
|
32
|
+
Multiple Log Pipeline Filters can be specified in the `logPipelineFilters` section. See the loki docs to learn more about the log pipeline filters and their values and usage: https://grafana.com/docs/loki/latest/query/log_queries/#log-pipeline
|
|
33
|
+
|
|
25
34
|
## Installation
|
|
26
35
|
|
|
27
36
|
To install this backend module:
|
package/config.d.ts
CHANGED
|
@@ -23,8 +23,22 @@ export interface Config {
|
|
|
23
23
|
loki?: {
|
|
24
24
|
/**
|
|
25
25
|
* Base URL of the Loki service.
|
|
26
|
+
* /loki/api/v1/query_range will be appended to the baseUrl
|
|
26
27
|
*/
|
|
27
28
|
baseUrl: string;
|
|
29
|
+
/**
|
|
30
|
+
* Auth Token for accessing the loki query url
|
|
31
|
+
*/
|
|
32
|
+
token: string;
|
|
33
|
+
/**
|
|
34
|
+
* Set to false if the baseUrl has a self-signed certificate
|
|
35
|
+
* defaults to true
|
|
36
|
+
*/
|
|
37
|
+
rejectUnauthorized?: boolean;
|
|
38
|
+
// Add custom log pipeline filters
|
|
39
|
+
// default is the workflow instanceId
|
|
40
|
+
// new values will be appened
|
|
41
|
+
logPipelineFilters?: Array<string>;
|
|
28
42
|
logStreamSelectors?: Array<{
|
|
29
43
|
// label is the selector, something like 'app' or 'service_name', etc...
|
|
30
44
|
label: string;
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var luxon = require('luxon');
|
|
4
|
+
var undici = require('undici');
|
|
4
5
|
|
|
5
6
|
class LokiProvider {
|
|
6
7
|
baseURL;
|
|
8
|
+
token;
|
|
7
9
|
selectors;
|
|
10
|
+
rejectUnauthorized;
|
|
11
|
+
logPipelineFilters;
|
|
8
12
|
constructor(config) {
|
|
9
13
|
this.baseURL = config.getString("baseUrl");
|
|
14
|
+
this.token = config.getString("token");
|
|
15
|
+
this.rejectUnauthorized = config.getOptionalBoolean("rejectUnauthorized") === false ? false : true;
|
|
10
16
|
this.selectors = config.getOptional("logStreamSelectors") || [];
|
|
17
|
+
this.logPipelineFilters = config.getOptional("logPipelineFilters") || [];
|
|
18
|
+
const agent = new undici.Agent({
|
|
19
|
+
connect: {
|
|
20
|
+
rejectUnauthorized: this.rejectUnauthorized
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
undici.setGlobalDispatcher(agent);
|
|
11
24
|
}
|
|
12
25
|
getBaseURL() {
|
|
13
26
|
return this.baseURL;
|
|
@@ -18,6 +31,12 @@ class LokiProvider {
|
|
|
18
31
|
getSelectors() {
|
|
19
32
|
return this.selectors;
|
|
20
33
|
}
|
|
34
|
+
getToken() {
|
|
35
|
+
return this.token;
|
|
36
|
+
}
|
|
37
|
+
getRejectUnauthorized() {
|
|
38
|
+
return this.rejectUnauthorized;
|
|
39
|
+
}
|
|
21
40
|
async fetchWorkflowLogsByInstance(instance) {
|
|
22
41
|
const startTime = luxon.DateTime.fromISO(instance.start, {
|
|
23
42
|
setZone: true
|
|
@@ -26,15 +45,20 @@ class LokiProvider {
|
|
|
26
45
|
const lokiApiEndpoint = "/loki/api/v1/query_range";
|
|
27
46
|
let streamSelector = "";
|
|
28
47
|
if (this.selectors.length < 1) {
|
|
29
|
-
streamSelector = '
|
|
48
|
+
streamSelector = 'openshift_log_type="application"';
|
|
30
49
|
} else {
|
|
31
50
|
this.selectors.forEach(
|
|
32
51
|
(entry, index, arr) => {
|
|
33
|
-
streamSelector += `${entry.label || "
|
|
52
|
+
streamSelector += `${entry.label || "openshift_log_type"}${entry.value || '=~".+"'}${index !== arr.length - 1 ? "," : ""}`;
|
|
34
53
|
}
|
|
35
54
|
);
|
|
36
55
|
}
|
|
37
|
-
|
|
56
|
+
let logPipelineFilter = `|="${instance.id}"`;
|
|
57
|
+
if (this.logPipelineFilters.length > 0) {
|
|
58
|
+
this.logPipelineFilters.forEach((element) => {
|
|
59
|
+
logPipelineFilter += ` ${element}`;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
38
62
|
const params = new URLSearchParams({
|
|
39
63
|
query: `{${streamSelector}} ${logPipelineFilter}`,
|
|
40
64
|
start: startTime,
|
|
@@ -43,7 +67,12 @@ class LokiProvider {
|
|
|
43
67
|
const urlToFetch = `${this.baseURL}${lokiApiEndpoint}?${params.toString()}`;
|
|
44
68
|
let allResults;
|
|
45
69
|
try {
|
|
46
|
-
const response = await fetch(urlToFetch
|
|
70
|
+
const response = await fetch(urlToFetch, {
|
|
71
|
+
headers: {
|
|
72
|
+
Authorization: `Bearer ${this.token}`,
|
|
73
|
+
"Content-Type": "application/json"
|
|
74
|
+
}
|
|
75
|
+
});
|
|
47
76
|
if (!response.ok) {
|
|
48
77
|
throw new Error(await response.text());
|
|
49
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LokiProvider.cjs.js","sources":["../../src/workflowLogsProviders/LokiProvider.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Config } from '@backstage/config';\nimport { DateTime } from 'luxon';\nimport {\n ProcessInstanceDTO,\n WorkflowLogsResponse,\n} from '@red-hat-developer-hub/backstage-plugin-orchestrator-common';\nimport { WorkflowLogProvider } from '@red-hat-developer-hub/backstage-plugin-orchestrator-node';\n\nexport class LokiProvider implements WorkflowLogProvider {\n private readonly baseURL: string;\n private readonly selectors: any;\n private constructor(config: Config) {\n this.baseURL = config.getString('baseUrl');\n this.selectors = config.getOptional('logStreamSelectors') || [];\n }\n getBaseURL(): string {\n return this.baseURL;\n }\n\n getProviderId() {\n return 'loki';\n }\n\n getSelectors() {\n return this.selectors;\n }\n\n async fetchWorkflowLogsByInstance(\n instance: ProcessInstanceDTO,\n ): Promise<WorkflowLogsResponse> {\n // Because of timing issues, subtract 5 mintues from the start and add 5 minutes to the end\n const startTime = DateTime.fromISO(instance.start as string, {\n setZone: true,\n })\n .minus({ minutes: 5 })\n .toISO();\n // Loki queries time range can't exceeds the limit (query length: 959h37m33.575s, limit: 30d1h)\n // If there is no end date specified, then just add 29 days to the start date\n // Assume that if there is an end date the range between start and end isn't more than 30 days\n const endTime = instance.end\n ? DateTime.fromISO(instance.end as string, { setZone: true })\n .plus({ minutes: 5 })\n .toISO()\n : DateTime.fromISO(instance.start as string, { setZone: true })\n .plus({ days: 29 })\n .toISO();\n const lokiApiEndpoint = '/loki/api/v1/query_range';\n // Query is created with a log stream selector and then a log pipeline for more filtering\n // format looks like this: {stream-selector=expression} | log pipeline/log filter expression\n // The log stream selector part of the query here is getting all service names\n // This might need to be configurable, based on https://grafana.com/docs/loki/latest/query/log_queries/#log-stream-selector\n // Log pipeline part looks for the workflow instance id in those logs\n // Create the streamSelector\n let streamSelector: string = '';\n if (this.selectors.length < 1) {\n streamSelector = 'service_name=~\".+\"';\n } else {\n this.selectors.forEach(\n (\n entry: { label: any; value: any },\n index: number,\n arr: string | any[],\n ) => {\n // something about that last comma\n streamSelector += `${entry.label || 'service_name'}${entry.value || '=~\".+\"'}${index !== arr.length - 1 ? ',' : ''}`;\n },\n );\n }\n const logPipelineFilter = `|=\"${instance.id}\"`;\n const params = new URLSearchParams({\n query: `{${streamSelector}} ${logPipelineFilter}`,\n start: startTime as string,\n end: endTime as string,\n });\n\n const urlToFetch = `${this.baseURL}${lokiApiEndpoint}?${params.toString()}`;\n\n let allResults;\n try {\n const response = await fetch(urlToFetch);\n if (!response.ok) {\n throw new Error(await response.text());\n }\n\n const jsonResponse = await response.json();\n\n /**\n Data should look like this\n {\n \"instanceId\": \"efe0490f-6300-453b-bcb6-f47eb7efbb36\",\n \"logs\": [\n {\n id: \"1763129443414066000\",\n log: \"2025-11-14 14:08:52,645 d5932f2cb566 INFO [org.kie.kogito.serverless.workflow.devservices.DevModeServerlessWorkflowLogger:40] (executor-thread-97) Starting workflow 'hello_world' (efe0490f-6300-453b-bcb6-f47eb7efbb36)\"\n },\n ...\n ]\n }\n */\n // flatMap and map the results to an array like this:\n /**\n * {\n * id: '123456',\n * log: '2025-11-14 14:08:52,645 d5932f2cb566 INFO [org.kie.kogito.serverless.workflow.devservices.De....'\n * }\n */\n allResults = jsonResponse.data.result\n .flatMap((val: any[]) => {\n return val.values;\n })\n .map((val: any[]) => {\n return {\n id: val[0],\n log: val[1],\n };\n });\n } catch (error) {\n throw new Error(`Problem fetching loki logs: ${error.message}`);\n }\n\n const workflowLogsResponse: WorkflowLogsResponse = {\n instanceId: instance.id,\n logs: allResults.sort((a: { id: number }, b: { id: number }) => {\n return Number(a.id) - Number(b.id);\n }),\n };\n return workflowLogsResponse;\n }\n\n static fromConfig(config: Config): LokiProvider {\n const lokiConfig = config.getConfig(\n 'orchestrator.workflowLogProvider.loki',\n );\n return new LokiProvider(lokiConfig);\n }\n}\n"],"names":["DateTime"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LokiProvider.cjs.js","sources":["../../src/workflowLogsProviders/LokiProvider.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Config } from '@backstage/config';\nimport { DateTime } from 'luxon';\nimport {\n ProcessInstanceDTO,\n WorkflowLogsResponse,\n} from '@red-hat-developer-hub/backstage-plugin-orchestrator-common';\nimport { WorkflowLogProvider } from '@red-hat-developer-hub/backstage-plugin-orchestrator-node';\n\nimport { Agent, setGlobalDispatcher } from 'undici';\n\nexport class LokiProvider implements WorkflowLogProvider {\n private readonly baseURL: string;\n private readonly token: string;\n private readonly selectors: any;\n private readonly rejectUnauthorized: boolean;\n private readonly logPipelineFilters: any;\n private constructor(config: Config) {\n this.baseURL = config.getString('baseUrl');\n this.token = config.getString('token');\n // Only should be false if specified, undefined here should be true\n this.rejectUnauthorized =\n config.getOptionalBoolean('rejectUnauthorized') === false ? false : true;\n this.selectors = config.getOptional('logStreamSelectors') || [];\n this.logPipelineFilters = config.getOptional('logPipelineFilters') || [];\n\n const agent = new Agent({\n connect: {\n rejectUnauthorized: this.rejectUnauthorized,\n },\n });\n setGlobalDispatcher(agent);\n }\n getBaseURL(): string {\n return this.baseURL;\n }\n\n getProviderId() {\n return 'loki';\n }\n\n getSelectors() {\n return this.selectors;\n }\n\n getToken(): string {\n return this.token;\n }\n\n getRejectUnauthorized(): boolean {\n return this.rejectUnauthorized;\n }\n\n async fetchWorkflowLogsByInstance(\n instance: ProcessInstanceDTO,\n ): Promise<WorkflowLogsResponse> {\n // Because of timing issues, subtract 5 mintues from the start and add 5 minutes to the end\n const startTime = DateTime.fromISO(instance.start as string, {\n setZone: true,\n })\n .minus({ minutes: 5 })\n .toISO();\n // Loki queries time range can't exceeds the limit (query length: 959h37m33.575s, limit: 30d1h)\n // If there is no end date specified, then just add 29 days to the start date\n // Assume that if there is an end date the range between start and end isn't more than 30 days\n const endTime = instance.end\n ? DateTime.fromISO(instance.end as string, { setZone: true })\n .plus({ minutes: 5 })\n .toISO()\n : DateTime.fromISO(instance.start as string, { setZone: true })\n .plus({ days: 29 })\n .toISO();\n const lokiApiEndpoint = '/loki/api/v1/query_range';\n // Query is created with a log stream selector and then a log pipeline for more filtering\n // format looks like this: {stream-selector=expression} | log pipeline/log filter expression\n // The log stream selector part of the query here is defaulting to openshift_log_type=application\n // This is the value used for Openshift Logging\n // This might need to be configurable, based on https://grafana.com/docs/loki/latest/query/log_queries/#log-stream-selector\n // Log pipeline part looks for the workflow instance id in those logs\n // Create the streamSelector\n let streamSelector: string = '';\n if (this.selectors.length < 1) {\n streamSelector = 'openshift_log_type=\"application\"';\n } else {\n this.selectors.forEach(\n (\n entry: { label: any; value: any },\n index: number,\n arr: string | any[],\n ) => {\n // something about that last comma\n streamSelector += `${entry.label || 'openshift_log_type'}${entry.value || '=~\".+\"'}${index !== arr.length - 1 ? ',' : ''}`;\n },\n );\n }\n let logPipelineFilter: string = `|=\"${instance.id}\"`;\n\n if (this.logPipelineFilters.length > 0) {\n this.logPipelineFilters.forEach((element: any) => {\n logPipelineFilter += ` ${element}`;\n });\n }\n\n const params = new URLSearchParams({\n query: `{${streamSelector}} ${logPipelineFilter}`,\n start: startTime as string,\n end: endTime as string,\n });\n\n const urlToFetch = `${this.baseURL}${lokiApiEndpoint}?${params.toString()}`;\n\n let allResults;\n try {\n const response = await fetch(urlToFetch, {\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n });\n if (!response.ok) {\n throw new Error(await response.text());\n }\n\n const jsonResponse = await response.json();\n\n /**\n Data should look like this\n {\n \"instanceId\": \"efe0490f-6300-453b-bcb6-f47eb7efbb36\",\n \"logs\": [\n {\n id: \"1763129443414066000\",\n log: \"2025-11-14 14:08:52,645 d5932f2cb566 INFO [org.kie.kogito.serverless.workflow.devservices.DevModeServerlessWorkflowLogger:40] (executor-thread-97) Starting workflow 'hello_world' (efe0490f-6300-453b-bcb6-f47eb7efbb36)\"\n },\n ...\n ]\n }\n */\n // flatMap and map the results to an array like this:\n /**\n * {\n * id: '123456',\n * log: '2025-11-14 14:08:52,645 d5932f2cb566 INFO [org.kie.kogito.serverless.workflow.devservices.De....'\n * }\n */\n allResults = jsonResponse.data.result\n .flatMap((val: any[]) => {\n return val.values;\n })\n .map((val: any[]) => {\n return {\n id: val[0],\n log: val[1],\n };\n });\n } catch (error) {\n throw new Error(`Problem fetching loki logs: ${error.message}`);\n }\n\n const workflowLogsResponse: WorkflowLogsResponse = {\n instanceId: instance.id,\n logs: allResults.sort((a: { id: number }, b: { id: number }) => {\n return Number(a.id) - Number(b.id);\n }),\n };\n return workflowLogsResponse;\n }\n\n static fromConfig(config: Config): LokiProvider {\n const lokiConfig = config.getConfig(\n 'orchestrator.workflowLogProvider.loki',\n );\n return new LokiProvider(lokiConfig);\n }\n}\n"],"names":["Agent","setGlobalDispatcher","DateTime"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@red-hat-developer-hub/backstage-plugin-orchestrator-backend-module-loki",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "The loki backend module for the orchestrator plugin.",
|
|
6
6
|
"main": "./dist/index.cjs.js",
|
|
@@ -46,9 +46,10 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@backstage/backend-plugin-api": "^1.6.2",
|
|
49
|
-
"@red-hat-developer-hub/backstage-plugin-orchestrator-common": "^3.5.
|
|
50
|
-
"@red-hat-developer-hub/backstage-plugin-orchestrator-node": "^1.1.
|
|
51
|
-
"luxon": "^3.7.2"
|
|
49
|
+
"@red-hat-developer-hub/backstage-plugin-orchestrator-common": "^3.5.2",
|
|
50
|
+
"@red-hat-developer-hub/backstage-plugin-orchestrator-node": "^1.1.2",
|
|
51
|
+
"luxon": "^3.7.2",
|
|
52
|
+
"undici": "^7.22.0"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"@backstage/backend-test-utils": "^1.10.4",
|