├── __tests__ ├── tests.ts ├── supertest.ts ├── enzyme.ts └── enzyme.tsx ├── src ├── favicon.png ├── components │ ├── goodnessgracious │ │ ├── types.ts │ │ ├── Library.tsx │ │ ├── Line.tsx │ │ ├── LineChart.tsx │ │ └── Vis2.tsx │ ├── UserPage │ │ ├── AccountInfo.tsx │ │ ├── SessionHistory.tsx │ │ ├── BrokerCard.tsx │ │ ├── LeftNav.tsx │ │ ├── AddTopicCard.tsx │ │ ├── UserPage.tsx │ │ ├── Gallery.tsx │ │ ├── TopNav.tsx │ │ ├── MessageMetrics.tsx │ │ ├── consumerMetrics.tsx │ │ ├── LeadMetrics.tsx │ │ ├── producerMetrics.tsx │ │ ├── BrokerDetails.tsx │ │ └── BrokerOverview.tsx │ ├── Navbar.tsx │ ├── App.tsx │ ├── Base │ │ ├── Home.tsx │ │ ├── Login.tsx │ │ ├── Signup.tsx │ │ └── About.tsx │ ├── Line.tsx │ ├── Dual.tsx │ ├── Testing.tsx │ ├── Vis2.tsx │ ├── Testing2.tsx │ └── Line2.tsx ├── index.html └── index.tsx ├── Dockerfile-dev ├── Dockerfile ├── docker-compose-dev-hot.yml ├── dummydbreq.js ├── tsconfig.json ├── server ├── routes │ ├── dbRouter.ts │ ├── userRouter.ts │ └── kafkaRouter.ts ├── dataStructures │ ├── test.js │ └── queue.js ├── models │ └── userModel.ts ├── server.ts ├── controllers │ ├── userController.ts │ ├── cookieController.ts │ └── kafkaController.ts └── kafkaApplication │ ├── topic.js │ ├── producer.js │ └── consumer.js ├── docker-compose.yml ├── webpack.config.js ├── .gitignore ├── README.md └── package.json /__tests__/tests.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /__tests__/supertest.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/deKaf/HEAD/src/favicon.png -------------------------------------------------------------------------------- /Dockerfile-dev: -------------------------------------------------------------------------------- 1 | FROM node:14.17 2 | RUN npm install webpack -g 3 | WORKDIR /usr/src/app 4 | COPY package*.json ./ 5 | RUN npm install 6 | EXPOSE 8080 -------------------------------------------------------------------------------- /src/components/goodnessgracious/types.ts: -------------------------------------------------------------------------------- 1 | 2 | export namespace Types { 3 | export type Data = { 4 | date: string, 5 | value: number 6 | } 7 | } -------------------------------------------------------------------------------- /src/components/goodnessgracious/Library.tsx: -------------------------------------------------------------------------------- 1 | 2 | const Library = () = { 3 | 4 | 5 | return ( 6 | 7 | ) 8 | } 9 | 10 | export default Library; -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14.17 2 | WORKDIR /usr/src/app 3 | COPY . . 4 | RUN npm install 5 | RUN npm run build 6 | EXPOSE 3000 7 | #CMD [ "node", "./server/server.js"] 8 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /docker-compose-dev-hot.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | dev: 4 | image: "teamdekaf/dekaf-dev" 5 | container_name: "dekaf-dev-hot" 6 | ports: 7 | - "8080:8080" 8 | volumes: 9 | - .:/usr/src/app 10 | - node_modules:/usr/src/app/node_modules 11 | command: npm run dev 12 | volumes: 13 | node_modules: -------------------------------------------------------------------------------- /dummydbreq.js: -------------------------------------------------------------------------------- 1 | const db = require('./server/models/userModel') 2 | 3 | async function addtodb() { 4 | const queryString = { 5 | text: 'INSERT INTO data (message, partition) VALUES ($1, $2)', 6 | values: ['test', 'partitiontest'], 7 | rowMode: 'array' 8 | } 9 | await db.query(queryString); 10 | return; 11 | } 12 | addtodb() 13 | .catch(err => console.log(`console log error ${err}`)) 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["es6", "dom"], 4 | "outDir": "./build/", 5 | "module": "commonjs", 6 | "target": "es6", 7 | "jsx": "preserve", 8 | "allowJs": true, 9 | "moduleResolution": "node", 10 | "allowSyntheticDefaultImports": true, 11 | "esModuleInterop": true 12 | }, 13 | "include": ["src/**/*"], 14 | "exclude": ["node_modules"], 15 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | deKaf 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { BrowserRouter as Router } from 'react-router-dom'; 4 | // @ts-ignore 5 | import App from './components/App.tsx'; 6 | // import styles for webpack, this is where we'd import a logo, and append it 7 | import './styles.scss'; 8 | 9 | render( 10 | 11 | 12 | , 13 | document.getElementById('root') 14 | ); -------------------------------------------------------------------------------- /src/components/UserPage/AccountInfo.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const AccountInfo = () => { 4 | return ( 5 |
6 |

Session history

7 |
8 | This will be a list of all previous sessions, pulled from the database, along with any other features we want to add 9 |
10 |
11 | ) 12 | } 13 | 14 | export default AccountInfo; -------------------------------------------------------------------------------- /src/components/UserPage/SessionHistory.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SessionHistory = () => { 4 | return ( 5 |
6 |

Session history

7 |
8 | This will be a list of all previous sessions, pulled from the database, along with any other features we want to add 9 |
10 |
11 | ) 12 | } 13 | 14 | export default SessionHistory; -------------------------------------------------------------------------------- /src/components/UserPage/BrokerCard.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | const BrokerCard = () => { 5 | return ( 6 |
7 |

Broker

8 |
9 |

Topics: 1

10 |

Partitions: 3

11 | 12 | 13 |
14 | ) 15 | } 16 | 17 | export default BrokerCard; -------------------------------------------------------------------------------- /src/components/UserPage/LeftNav.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | const LeftNav = () => { 5 | return ( 6 | 11 | ) 12 | } 13 | 14 | export default LeftNav; -------------------------------------------------------------------------------- /src/components/UserPage/AddTopicCard.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | const AddTopicCard = () => { 5 | return ( 6 |
7 |

Add a new topic

8 |
9 |

Topic name:

10 |

Partitions:

11 | 12 | {/* */} 13 |
14 | ) 15 | } 16 | 17 | export default AddTopicCard; -------------------------------------------------------------------------------- /server/routes/dbRouter.ts: -------------------------------------------------------------------------------- 1 | // //** Requiring in express.Router**// 2 | 3 | // const expressImport = require('express'); 4 | // const routerDB = expressImport.Router(); 5 | 6 | // //** Path to file controllers**// 7 | // const userControllerFiles = require("../controllers/userController.ts"); 8 | // const dbControllerFiles = require("../controllers/dbController.ts"); 9 | // const kafkaControllerFiles = require("../controllers/kafkaController.ts"); 10 | // const cookieControllerFiles = require("../controllers/cookieController.ts"); 11 | 12 | // // routerDB.get('/data'); 13 | 14 | // module.exports = routerDB; -------------------------------------------------------------------------------- /server/dataStructures/test.js: -------------------------------------------------------------------------------- 1 | const dataStructures = require('../dataStructures/queue.js') 2 | const db = require('../models/userModel'); 3 | function test() { 4 | const messageQ = 'this is a big test'; 5 | const partition = 25; 6 | const queryString = { 7 | text: 'INSERT INTO data2 (message, partition) VALUES ($1, $2)', 8 | values: [messageQ, partition], 9 | rowMode: 'array' 10 | } 11 | console.log('before query') 12 | db.query(queryString) 13 | .catch(e => console.log(`error in addTodb`, e)); 14 | // const buffer = new dataStructures() 15 | // buffer.print(); 16 | } 17 | 18 | 19 | // test() -------------------------------------------------------------------------------- /src/components/Navbar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | const NavBar = () => { 5 | return ( 6 | 14 | ) 15 | } 16 | 17 | export default NavBar; -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | zookeeper: 4 | image: 'bitnami/zookeeper:latest' 5 | ports: 6 | - '2181:2181' 7 | environment: 8 | - ALLOW_ANONYMOUS_LOGIN=yes 9 | kafka: 10 | image: 'bitnami/kafka:latest' 11 | 12 | container_name: 'kafkaPP26' 13 | 14 | ports: 15 | - '9092:9092' 16 | environment: 17 | - KAFKA_BROKER_ID=1 18 | - KAFKA_LISTENERS=PLAINTEXT://:9092 19 | - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://127.0.0.1:9092 20 | - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 21 | - ALLOW_PLAINTEXT_LISTENER=yes 22 | depends_on: 23 | - zookeeper 24 | -------------------------------------------------------------------------------- /src/components/UserPage/UserPage.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { useHistory } from 'react-router-dom'; 3 | // @ts-ignore 4 | import LeftNav from './LeftNav.tsx'; 5 | // @ts-ignore 6 | import Gallery from './Gallery.tsx'; 7 | 8 | const UserPage = () => { 9 | const history = useHistory(); 10 | 11 | useEffect (() => { 12 | fetch('/user/verifySession') 13 | .then(data => data.json()) 14 | .then(data => { 15 | if (data === 'failed') history.push('/'); 16 | }) 17 | }, []) 18 | 19 | return ( 20 |
21 | 22 | 23 |
24 | ) 25 | } 26 | 27 | export default UserPage; -------------------------------------------------------------------------------- /src/components/UserPage/Gallery.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router, Route, Switch, useLocation } from 'react-router-dom'; 3 | // @ts-ignore 4 | import BrokerOverview from './BrokerOverview.tsx'; 5 | // @ts-ignore 6 | import BrokerDetails from './BrokerDetails.tsx'; 7 | // @ts-ignore 8 | import SessionHistory from './SessionHistory.tsx'; 9 | 10 | const Gallery = () => { 11 | return ( 12 |
13 | 14 | } /> 15 | } /> 16 | } /> 17 | 18 |
19 | ) 20 | } 21 | 22 | export default Gallery; -------------------------------------------------------------------------------- /src/components/UserPage/TopNav.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link, useHistory } from 'react-router-dom'; 3 | 4 | const TopNav = () => { 5 | const history = useHistory(); 6 | 7 | const logout = () => { 8 | fetch('/user/logout', { method: 'POST', credentials: 'include' }) 9 | .then(data => data.json()) 10 | .then(() => history.push('/')) 11 | .catch(err => console.log('ERROR LOGGING OUT: ', err)) 12 | } 13 | 14 | return ( 15 | 23 | ) 24 | } 25 | 26 | export default TopNav; -------------------------------------------------------------------------------- /server/dataStructures/queue.js: -------------------------------------------------------------------------------- 1 | const db = require('../models/userModel') 2 | 3 | class dataStructures { 4 | constructor() { 5 | this.messageArray = []; 6 | } 7 | 8 | queue(data) { 9 | this.messageArray.push(data); 10 | console.log(this.messageArray) 11 | // addToDb(data) 12 | } 13 | 14 | print(){ 15 | console.log(this.messageArray) 16 | } 17 | } 18 | 19 | const test = new dataStructures() 20 | test.print() 21 | 22 | async function addToDb(data) { 23 | const { value, partition } = data; 24 | const queryString = { 25 | text: 'INSERT INTO data (message, partition) VALUES ($1, $2)', 26 | values: [value, partition], 27 | rowMode: 'array' 28 | } 29 | await db.query(queryString); 30 | return; 31 | } 32 | // caddToDb({}) 33 | 34 | module.exports = dataStructures; 35 | // const queue = { 36 | // messageArray: [] 37 | // }; 38 | 39 | // queue.add = (currentMessage) => { 40 | // console.log('in the queue') 41 | // this.messageArray.push(currentMessage); 42 | // console.log(messageArray) 43 | // return; 44 | // } -------------------------------------------------------------------------------- /server/routes/userRouter.ts: -------------------------------------------------------------------------------- 1 | //** Requiring in express.Router**// 2 | 3 | const expressUser = require('express'); 4 | const routerUser = expressUser.Router(); 5 | 6 | //** Path to file controllers**// 7 | const userControllerUser = require("../controllers/userController.ts"); 8 | const kafkaControllerUser = require("../controllers/kafkaController.ts"); 9 | const cookieControllerUser = require("../controllers/cookieController.ts"); 10 | 11 | 12 | routerUser.post('/signup', userControllerUser.createUser, cookieControllerUser.createSessionCookie, (req, res) => { 13 | res.status(200).json('success'); 14 | }); 15 | 16 | routerUser.post('/login', userControllerUser.verifyUser, cookieControllerUser.createSessionCookie, (req, res) => { 17 | res.status(200).json('success'); 18 | }); 19 | 20 | routerUser.post('/logout', cookieControllerUser.deleteSessionCookie, (req, res) => { 21 | res.status(200).json('success'); 22 | }); 23 | 24 | routerUser.get('/verifySession', cookieControllerUser.sessionValidation, (req, res) => { 25 | res.status(200).json('success'); 26 | }); 27 | 28 | module.exports = routerUser; -------------------------------------------------------------------------------- /src/components/UserPage/MessageMetrics.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | // @ts-ignore 3 | import Vis from '../Vis.tsx'; 4 | 5 | const MessageMetrics = (props) => { 6 | 7 | if (!props.data) { 8 | return ( 9 |
10 |
11 |

Total messages in consumer

12 |
Loading messages...
13 |
14 |
15 | ) 16 | } else { 17 | return ( 18 |
19 |
20 |

Latest message:

21 |

{props.data.messageData[props.data.messageData.length - 1].value}

22 |

Partition:

23 |

{props.data.messageData[props.data.messageData.length - 1].partition}

24 |
25 |
26 |

Total messages in consumer

27 |
{props.data.messageCounter}
28 |
29 |
30 | ) 31 | } 32 | } 33 | 34 | export default MessageMetrics; -------------------------------------------------------------------------------- /__tests__/enzyme.ts: -------------------------------------------------------------------------------- 1 | // import React from 'react' 2 | // import {shallow} from 'enzyme' 3 | 4 | // //================================================== 5 | // // @ts-ignore 6 | // import Vis from '../src/components/Vis.tsx' 7 | // // @ts-ignore 8 | // import Vis2 from '../src/components/Vis2.tsx' 9 | // // @ts-ignore 10 | // import Line from '../src/components/Line' 11 | // import { isExportDeclaration, textSpanContainsPosition } from 'typescript' 12 | 13 | //================================================== 14 | 15 | describe('', () => { 16 | let component 17 | 18 | beforeEach(() => { 19 | component = shallow() 20 | }) 21 | 22 | test('Should mount', () => { 23 | expect(component.length).toBe(1) 24 | }) 25 | 26 | }) 27 | 28 | describe('', () => { 29 | let component 30 | 31 | beforeEach(() => { 32 | component = shallow() 33 | }) 34 | 35 | test('Should mount', () => { 36 | expect(component.length).toBe(1) 37 | }) 38 | 39 | }) 40 | 41 | describe('', () => { 42 | let component 43 | 44 | beforeEach(() => { 45 | component = shallow() 46 | }) 47 | 48 | test('Should mount', () => { 49 | expect(component.length).toBe(1) 50 | }) 51 | 52 | }) -------------------------------------------------------------------------------- /src/components/UserPage/consumerMetrics.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | // @ts-ignore 3 | import Vis from '../Vis.tsx'; 4 | // @ts-ignore 5 | import Line from '../Line.tsx' 6 | 7 | const ConsumerMetrics = (props) => { 8 | 9 | if (!props.data) { 10 | return ( 11 |
12 |
13 |

Consumer metrics

14 |
Loading consumer data...
15 |
16 |
17 | ) 18 | } else { 19 | 20 | const quantity = {}; 21 | const size = {}; 22 | 23 | for (let i = 0; i < props.data.requestData.length; i += 1) { 24 | const message = props.data.requestData[i]; 25 | quantity[message.createdAt] = i; 26 | size[i] = message.size; 27 | } 28 | 29 | return ( 30 |
31 |
32 |

Consumer metrics

33 |

Total messages received by consumer: {props.data.requestCounter}

34 |
35 | 36 |
37 |

Message quantity over time

38 | } 39 |
40 |
41 | 42 |
43 |

Message size

44 | 45 |
46 |
47 |
48 | ) 49 | } 50 | } 51 | 52 | export default ConsumerMetrics; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | 5 | // mode set to currect process 6 | mode: process.env.NODE_ENV, 7 | //entry point for compiling 8 | entry: './src/index.tsx', 9 | output: { 10 | //path to our build directory 11 | path: path.resolve(__dirname, 'build'), 12 | //compiled program file name 13 | filename: 'bundle.js', 14 | }, 15 | devServer: { 16 | publicPath: '/build', 17 | // Requests proxied to localhost:3000 when in dev build 18 | proxy: { 19 | "/": "http://localhost:3000" 20 | }, 21 | }, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.(ts|tsx)$/, 26 | exclude: /node_modules/, 27 | use: { 28 | // Translates React to js 29 | loader: 'babel-loader', 30 | options: { 31 | presets: ['@babel/preset-env','@babel/preset-react', '@babel/preset-typescript'] 32 | } 33 | } 34 | }, 35 | { 36 | test: /\.s[ac]ss$/, 37 | exclude: /node_modules/, 38 | use: [ 39 | 'style-loader', 40 | 'css-loader', 41 | 'sass-loader' 42 | ] 43 | }, 44 | { 45 | test: /\.(gif|png|jpe?g|svg)$/i, 46 | use: { 47 | // Compiles images, if we want to use a logo later on 48 | loader: 'file-loader', 49 | } 50 | } 51 | ] 52 | } 53 | } -------------------------------------------------------------------------------- /src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import {select} from 'd3-selection'; 3 | // @ts-ignore 4 | import Vis from './Vis.tsx'; 5 | import { Route, Switch } from 'react-router-dom'; 6 | 7 | // @ts-ignore 8 | import NavBar from './Navbar.tsx'; 9 | // @ts-ignore 10 | import TopNav from './UserPage/TopNav.tsx'; 11 | // @ts-ignore 12 | import Home from './Base/Home.tsx'; 13 | // @ts-ignore 14 | import Login from './Base/Login.tsx'; 15 | // @ts-ignore 16 | import Signup from './Base/Signup.tsx'; 17 | // @ts-ignore 18 | import About from './Base/About.tsx'; 19 | // @ts-ignore 20 | import UserPage from './UserPage/UserPage.tsx'; 21 | 22 | const App = () => { 23 | 24 | return ( 25 |
26 | {/* */} 27 | 28 | } /> 29 | } /> 30 | } /> 31 | } /> 32 | 33 |
34 | 35 | } /> 36 | } /> 37 | } /> 38 | } /> 39 | } /> 40 | } /> 41 | } /> 42 | 43 |
44 |
45 | ) 46 | } 47 | 48 | export default App; -------------------------------------------------------------------------------- /server/models/userModel.ts: -------------------------------------------------------------------------------- 1 | const { Pool } = require("pg"); 2 | require('dotenv').config(); 3 | 4 | 5 | //URI to elephantSQL database that will store the users favorite plants and any notes that add to those faves 6 | const PG_URI = process.env['PGURI']; 7 | 8 | //create a new pool here using the connection string above 9 | const pool = new Pool({ 10 | 11 | connectionString: PG_URI, 12 | 13 | // connectionString: process.env['PGCONNECT'], 14 | // user: process.env['PGUSER'], 15 | // password: process.env['PGPASSWORD'], 16 | // host: process.env['PGHOST'], 17 | // database: process.env['PGDATABASE'], 18 | // port: process.env['PGPORT'], 19 | }); 20 | 21 | // We export an object that contains a property called query, 22 | // which is a function that returns the invocation of pool.query() after logging the query 23 | // This will be required in the controllers to be the access point to the database 24 | 25 | // exporting module with some console logs 26 | 27 | module.exports = { 28 | query: async (text, params, callback) => { 29 | const client = await pool.connect(); 30 | let res; 31 | 32 | try{ 33 | await client.query('BEGIN'); 34 | res = await client.query(text, params, callback); 35 | await client.query('COMMIT'); 36 | } catch (e) { 37 | await client.query('ROLLBACK'); 38 | console.error(e); 39 | } finally { 40 | console.log('in the userModel finally') 41 | client.release(); 42 | } 43 | return res; 44 | }, 45 | }; 46 | 47 | 48 | // module.exports = { 49 | // query: (text, params, callback) => { 50 | // // console.log("executed query", text); 51 | // params = pool.connectionString; 52 | // // console.log("executed params", params); 53 | // // console.log("executed callback", callback); 54 | // return pool.query(text, params, callback); 55 | // }, 56 | // }; 57 | 58 | //send grid 59 | -------------------------------------------------------------------------------- /src/components/UserPage/LeadMetrics.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | // @ts-ignore 3 | import BrokerCard from './BrokerCard.tsx'; 4 | // @ts-ignore 5 | import Vis from '../Vis.tsx'; 6 | // @ts-ignore 7 | import Vis2 from '../Vis2.tsx'; 8 | // @ts-ignore 9 | import Testing from '../Testing.tsx' 10 | 11 | const LeadMetrics = (props) => { 12 | console.log('props.data:') 13 | console.log(props.data) 14 | if (!props.data) { 15 | return ( 16 |
17 |

Key metrics at a glance

18 |
Loading Topics...
19 |
20 | ) 21 | } else { 22 | 23 | const topicsArray = []; 24 | for (let index in props.data.partitionQuantity) { 25 | console.log(index) 26 | console.log(props.data.partitionQuantity) 27 | topicsArray.push( 28 |
29 |

Topic: {props.data.partitionQuantity[index].name}

30 |

Partitions: {props.data.partitionQuantity[index].partitionQuantity}

31 |
32 | ); 33 | } 34 | return ( 35 |
36 |
37 |

Topics and partitions

38 |
39 |
{topicsArray}
40 |
41 | 42 |
43 |

Quantity of messages per partition

44 |
45 |
46 |
47 |
48 | ) 49 | } 50 | } 51 | 52 | export default LeadMetrics; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Extra ignores 107 | build/ 108 | package-lock 109 | 110 | # error log 111 | myapp.log 112 | 113 | #mock data 114 | mockData.js -------------------------------------------------------------------------------- /src/components/UserPage/producerMetrics.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | // @ts-ignore 3 | import Vis from '../Vis.tsx'; 4 | // @ts-ignore 5 | import Vis2 from '../Vis2.tsx'; 6 | // @ts-ignore 7 | import Line from '../Line.tsx'; 8 | // @ts-ignore 9 | import Dual from '../Dual.tsx' 10 | // @ts-ignore 11 | import Testing from '../Testing.tsx' 12 | // @ts-ignore 13 | import Testing2 from '../Testing2.tsx' 14 | 15 | const ProducerMetrics = (props) => { 16 | 17 | const [sizeGraphData, setsizeGraphData] = useState(null); 18 | const [timeGraphData, settimeGraphData] = useState(null); 19 | 20 | if (!props.data) { 21 | 22 | return ( 23 |
24 |
25 |

Producer metrics

26 |
Loading producer data...
27 |
28 |
29 | ) 30 | } else { 31 | 32 | const quantity = {}; 33 | const size = {}; 34 | 35 | for (let i = 0; i < props.data.producerData.length; i += 1) { 36 | const message = props.data.producerData[i]; 37 | 38 | quantity[message.createdAt] = i; 39 | 40 | size[i] = message.size; 41 | 42 | 43 | } 44 | 45 | return ( 46 |
47 |
48 |

Producer metrics

49 | {/* */} 50 |

Total messages sent by producer: {props.data.producerCounter}

51 | {/* */} 52 |

Total messages sent by producer: {props.data.producerCounter}

53 |
54 | 55 |
56 |

Message quantity over time

57 | 58 |
59 |
60 | 61 |
62 |

Message size

63 | 64 |
65 |
66 |
67 | ) 68 | } 69 | } 70 | // } 71 | 72 | export default ProducerMetrics; -------------------------------------------------------------------------------- /src/components/Base/Home.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | const Home = () => { 5 | return ( 6 |
7 |
8 |
9 |
A web-based visualization tool for Kafka consumer metrics
10 |
11 | 12 | 15 | 16 | 17 | 20 | 21 | 22 | 25 | 26 |
27 |
28 | 29 |
30 |
31 |
32 |

Intuitive

33 |

Easily view key metrics on your Kafka instance with our intuitive web GUI.

34 |
35 |
36 |
37 |

Lightweight

38 |

No installation required; just enter your information and start using deKaf!

39 |
40 |
41 |
42 |

Real-time

43 |

Metrics update automatically as long as you're signed in, so you won't miss a beat.

44 |
45 |
46 |
47 | ) 48 | } 49 | 50 | export default Home; -------------------------------------------------------------------------------- /server/server.ts: -------------------------------------------------------------------------------- 1 | //** Express server imports **// 2 | const express = require('express'); 3 | const cookieParser = require('cookie-parser'); 4 | const app = express(); 5 | const PORT = 3000; 6 | 7 | //** Additional imports **// 8 | const path = require('path'); 9 | 10 | //require routers 11 | const kafkaRouter = require("./routes/kafkaRouter.ts"); 12 | const userRouter = require("./routes/userRouter.ts"); 13 | 14 | //** Serve all compiled files when running the production build **// 15 | app.use(express.static(path.resolve(__dirname, '../src'))); 16 | app.use('/build', express.static(path.join(__dirname, '../build'))); 17 | 18 | //** Automatically parse urlencoded body content from incoming requests and place it in req.body **// 19 | app.use(express.json()); 20 | app.use(express.urlencoded({ extended:true })); 21 | app.use(cookieParser()); 22 | 23 | 24 | //** Route handler to serve the basic file in case of no webpack build **// 25 | app.get('/', (req, res) => { 26 | return res.status(200).sendFile(path.join(__dirname, '../src/index.html')); 27 | }); 28 | 29 | //functionality routes 30 | app.use('/user', userRouter); 31 | app.use('/kafka', kafkaRouter); 32 | // app.use('/db', dbRouter); 33 | 34 | 35 | //** Middleware to serve the main html file **// 36 | const serveMainFile = (req, res) => { 37 | return res.status(200).sendFile(path.join(__dirname, '../src/index.html')); 38 | } 39 | 40 | //** Routes requiring main file **// 41 | app.get('/', serveMainFile); 42 | app.get('/login', serveMainFile); 43 | app.get('/signup', serveMainFile); 44 | app.get('/about', serveMainFile); 45 | app.get('/user', serveMainFile); 46 | app.get('/details', serveMainFile); 47 | app.get('/history', serveMainFile); 48 | 49 | //Router for kafka related requests 50 | app.use('/kafka', kafkaRouter) 51 | 52 | 53 | //** No route / 404 Handler **// 54 | app.use('*', (req, res) => res.status(404).send('Error 404: This page doesn\'t exist!')); 55 | 56 | //** Global Error Handler **// 57 | app.use((err, req, res, next) => { 58 | const defaultErr = { 59 | log: 'Express error handler caught unknown middleware error', 60 | status: 500, 61 | message: { err: 'An error occurred' }, 62 | }; 63 | const errorObj = Object.assign({}, defaultErr, err); 64 | console.log(errorObj.log); 65 | return res.status(errorObj.status).json(errorObj.message); 66 | }); 67 | 68 | app.listen(PORT, () =>{console.log(`Server is up and listening on port ${PORT}.`)}); 69 | 70 | module.exports = app; -------------------------------------------------------------------------------- /__tests__/enzyme.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { configure, shallow, mount } from 'enzyme'; 3 | import MemoryRouter from 'react-router-dom'; 4 | import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; 5 | import toJson from 'enzyme-to-json'; 6 | 7 | import UserPage from '../src/components/UserPage/UserPage'; 8 | import LeftNav from '../src/components/UserPage/LeftNav'; 9 | import Gallery from '../src/components/UserPage/Gallery'; 10 | import BrokerDetails from '../src/components/UserPage/BrokerDetails'; 11 | 12 | configure({ adapter: new Adapter() }); 13 | 14 | describe('Hello, Enzyme!', () => { 15 | it('renders', () => { 16 | const wrapper = shallow(
17 |

Hello, Enzyme!

18 |
); 19 | expect(wrapper.find('h1').html()).toMatch(/Hello, Enzyme/); 20 | }); 21 | }); 22 | 23 | describe('React unit tests', () => { 24 | describe('UserPage', () => { 25 | let wrapper; 26 | 27 | beforeAll(() => { 28 | wrapper = shallow() 29 | }); 30 | 31 | it('Renders a
tag with id user-wrapper', () => { 32 | expect(wrapper.type()).toEqual('div'); 33 | expect(wrapper.find('#user-wrapper')); 34 | }); 35 | }); 36 | 37 | describe('LeftNav', () => { 38 | let wrapper; 39 | 40 | beforeAll(() => { 41 | wrapper = shallow() 42 | }); 43 | 44 | it('Renders a