@miketako3/cloki 0.1.0
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/LICENSE +21 -0
- package/README.md +40 -0
- package/biome.json +15 -0
- package/package.json +38 -0
- package/src/index.ts +1 -0
- package/src/logger.ts +160 -0
- package/tsconfig.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 MikeTako
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Cloki - Simple Logging from Cloudflare Workers to Grafana Cloud's Loki
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
Welcome to **Cloki**, an open-source logger designed to bridge Cloudflare Workers with Grafana Cloud's Loki seamlessly and efficiently. Targeted at individual developers, Cloki aims to reduce maintenance costs while offering a straightforward logging solution. With minimal configuration and the sole use of the fetch API, Cloki is an easy-to-implement tool for effective logging.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Easy Integration**: Connect Cloudflare Workers with Grafana Cloud's Loki effortlessly.
|
|
10
|
+
- **Minimal Configuration**: Get started with just a few simple settings.
|
|
11
|
+
- **Cost-Effective**: Designed for developers looking to minimize overhead costs.
|
|
12
|
+
- **Pure Fetch API Usage**: No complex dependencies or setups, just the fetch API.
|
|
13
|
+
|
|
14
|
+
## Getting Started
|
|
15
|
+
|
|
16
|
+
TBD
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
TBD
|
|
21
|
+
|
|
22
|
+
## Contributing
|
|
23
|
+
|
|
24
|
+
Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
|
|
25
|
+
|
|
26
|
+
- Fork the Project
|
|
27
|
+
- Create your Feature Branch (git checkout -b feature/AmazingFeature)
|
|
28
|
+
- Commit your Changes (git commit -m 'Add some AmazingFeature')
|
|
29
|
+
- Push to the Branch (git push origin feature/AmazingFeature)
|
|
30
|
+
- Open a Pull Request
|
|
31
|
+
|
|
32
|
+
## License
|
|
33
|
+
|
|
34
|
+
Distributed under the MIT License. See **LICENSE** for more information.
|
|
35
|
+
|
|
36
|
+
## Contacts
|
|
37
|
+
|
|
38
|
+
miketako3 (Kaito Hiruta) - contact@miketako.xyz
|
|
39
|
+
|
|
40
|
+
Project Link: https://github.com/miketako3/cloki
|
package/biome.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/1.5.2/schema.json",
|
|
3
|
+
"organizeImports": {
|
|
4
|
+
"enabled": true
|
|
5
|
+
},
|
|
6
|
+
"linter": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"rules": {
|
|
9
|
+
"recommended": true
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": {
|
|
13
|
+
"ignore": ["dist/*.js", "dist/*.d.ts", "dist/*.d.ts.map", "dist/*.js.map"]
|
|
14
|
+
}
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@miketako3/cloki",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "cloki is logger library for Loki and Cloudflare Workers.",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"format": "npx @biomejs/biome format . --write",
|
|
12
|
+
"lint": "npx @biomejs/biome lint .",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/miketako3/cloki.git"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"cloudflare",
|
|
21
|
+
"workers",
|
|
22
|
+
"loki",
|
|
23
|
+
"grafana",
|
|
24
|
+
"logger",
|
|
25
|
+
"logging"
|
|
26
|
+
],
|
|
27
|
+
"author": "miketako3 (Kaito Hiruta)",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/miketako3/cloki/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/miketako3/cloki#readme",
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@biomejs/biome": "1.5.2",
|
|
35
|
+
"@types/node": "^20.11.5",
|
|
36
|
+
"typescript": "^5.3.3"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { getLokiLogger } from "./logger";
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loki config
|
|
3
|
+
*/
|
|
4
|
+
type LokiConfig = {
|
|
5
|
+
lokiHost: string;
|
|
6
|
+
lokiToken: string;
|
|
7
|
+
lokiUser: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Loki labels
|
|
12
|
+
*/
|
|
13
|
+
type LokiLabels = {
|
|
14
|
+
[key: string]: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Loki message
|
|
19
|
+
*/
|
|
20
|
+
type LokiMessage = {
|
|
21
|
+
streams: [
|
|
22
|
+
{
|
|
23
|
+
stream: LokiLabels;
|
|
24
|
+
values: [string[]];
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create a Loki logger
|
|
31
|
+
* logger has some async logging methods like info, error, warn, etc.
|
|
32
|
+
*
|
|
33
|
+
* @param config
|
|
34
|
+
*/
|
|
35
|
+
export const getLokiLogger = (
|
|
36
|
+
config: LokiConfig,
|
|
37
|
+
): {
|
|
38
|
+
info: (message: object) => Promise<void>;
|
|
39
|
+
warn: (message: object) => Promise<void>;
|
|
40
|
+
error: (message: object) => Promise<void>;
|
|
41
|
+
debug: (message: object) => Promise<void>;
|
|
42
|
+
} => {
|
|
43
|
+
return {
|
|
44
|
+
info: lokiInfo(config),
|
|
45
|
+
warn: lokiWarn(config),
|
|
46
|
+
error: lokiError(config),
|
|
47
|
+
debug: lokiDebug(config),
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Log info to Loki curried
|
|
53
|
+
*
|
|
54
|
+
* @param config
|
|
55
|
+
*/
|
|
56
|
+
const lokiInfo =
|
|
57
|
+
(config: LokiConfig) =>
|
|
58
|
+
async (message: object, labels: LokiLabels = {}) => {
|
|
59
|
+
await log(config, "info", message, labels);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Log warn to Loki curried
|
|
64
|
+
*
|
|
65
|
+
* @param config
|
|
66
|
+
*/
|
|
67
|
+
const lokiWarn =
|
|
68
|
+
(config: LokiConfig) =>
|
|
69
|
+
async (message: object, labels: LokiLabels = {}) => {
|
|
70
|
+
await log(config, "warn", message, labels);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Log error to Loki curried
|
|
75
|
+
*
|
|
76
|
+
* @param config
|
|
77
|
+
*/
|
|
78
|
+
const lokiError =
|
|
79
|
+
(config: LokiConfig) =>
|
|
80
|
+
async (message: object, labels: LokiLabels = {}) => {
|
|
81
|
+
await log(config, "error", message, labels);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Log debug to Loki curried
|
|
86
|
+
*
|
|
87
|
+
* @param config
|
|
88
|
+
*/
|
|
89
|
+
const lokiDebug =
|
|
90
|
+
(config: LokiConfig) =>
|
|
91
|
+
async (message: object, labels: LokiLabels = {}) => {
|
|
92
|
+
await log(config, "debug", message, labels);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Log to Loki
|
|
97
|
+
*
|
|
98
|
+
* @param config
|
|
99
|
+
* @param logLevel
|
|
100
|
+
* @param message
|
|
101
|
+
* @param labels
|
|
102
|
+
*/
|
|
103
|
+
async function log(
|
|
104
|
+
config: LokiConfig,
|
|
105
|
+
logLevel: string,
|
|
106
|
+
message: object,
|
|
107
|
+
labels: LokiLabels,
|
|
108
|
+
) {
|
|
109
|
+
console.log(message);
|
|
110
|
+
const lokiMessage = generateLokiMessage(logLevel, message, labels);
|
|
111
|
+
await sendToLoki(config, lokiMessage);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Generate a Loki message object
|
|
116
|
+
*
|
|
117
|
+
* @param logLevel
|
|
118
|
+
* @param message
|
|
119
|
+
* @param labels
|
|
120
|
+
*/
|
|
121
|
+
function generateLokiMessage(
|
|
122
|
+
logLevel: string,
|
|
123
|
+
message: object,
|
|
124
|
+
labels: LokiLabels,
|
|
125
|
+
): LokiMessage {
|
|
126
|
+
return {
|
|
127
|
+
streams: [
|
|
128
|
+
{
|
|
129
|
+
stream: {
|
|
130
|
+
level: logLevel,
|
|
131
|
+
...labels,
|
|
132
|
+
},
|
|
133
|
+
values: [[`${Date.now().toString()}000000`, message.toString()]],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Send a message to Loki
|
|
141
|
+
*
|
|
142
|
+
* @param config
|
|
143
|
+
* @param lokiMessage
|
|
144
|
+
*/
|
|
145
|
+
async function sendToLoki(config: LokiConfig, lokiMessage: LokiMessage) {
|
|
146
|
+
try {
|
|
147
|
+
await fetch(
|
|
148
|
+
`https://${config.lokiUser}:${config.lokiToken}@${config.lokiHost}/loki/api/v1/push`,
|
|
149
|
+
{
|
|
150
|
+
method: "POST",
|
|
151
|
+
headers: {
|
|
152
|
+
"Content-Type": "application/json",
|
|
153
|
+
},
|
|
154
|
+
body: JSON.stringify(lokiMessage),
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
} catch (e) {
|
|
158
|
+
console.log("Send message to Loki was failed. : {}", e);
|
|
159
|
+
}
|
|
160
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2016",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"sourceMap": true,
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"forceConsistentCasingInFileNames": true,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"outDir": "./dist",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"skipLibCheck": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*.ts"]
|
|
14
|
+
}
|