Grafana로 데이터 들어오는 것 확인하기 👉

SEUNGHWANLEE·2021년 2월 14일
0

Mobius Guideline

목록 보기
10/11
post-thumbnail

Grafana란, 시계열 매트릭 데이터를 시각화 하는데 가장 최적화된 대시보드를 제공해주는 오픈소스 툴킷이다.

- ShinChul Bang, FINDA 기술블로그 Apr 23, 2020

Grafana는 실시간 데이터를 가져오기 때문에, 실시간 데이터베이스가 필요했습니다. MySQL실시간 데이터베이스가 아니기 때문에 넣는 데이터를 타임스탬프와 해당 값들을 새롭게 데이터베이스에 저장해주었습니다.


MySQL Listener 만들기

MySQL을 real-time database처럼 사용하기 위해서 localhost:3306를 listen하는 간단한 서버를 만들었습니다. seunghwanly/mobius-docker/mobius/ 디렉토리안에 mysql_radar로 만들어두었습니다. 약간의 코드 설명을 하자면 구조는 다음과 같이 이루어져있습니다.

mysql_radar
└───node_modules
│   .env
│   connection.js
│   grafanadb.sql
│   index.js
│   package-lock.json
│   package.json
|   parse.js
  • .env 파일은 새롭게 생성하여, MySQL에 설정하신 비밀번호와 listen할 데이터베이스이름과 포트를 입력해주시면됩니다.

    DB_PASSWORD=Password789!
    DB_NAME=mobiusdb
    DB_PORT=3306
  • connection.js는 'grafana'라는 DB(데이터베이스)를 생성하여 해당 데이터베이스를 연결하는 역할을 해줍니다. connectionInfo안에 정보들을 담아 init()connect()함수를 만들어 사용하였습니다.

  • index.js는 MySQL를 사용하여 두개의 데이터베이스에 접근합니다. 먼저 '@rodrigogs/mysql-events'를 이용하여 레이더에서 수신해온 데이터가 저장되는 mobiusdblisten합니다. 그리고 connection.js에서 설정한 함수와 import한 패키지를 이용하여 listen해서 들어온 data를 grafana 데이터베이스에 저장해줍니다.

    const program = async () => {
        const connection = mysql.createConnection({
            host: 'localhost',
            user: 'root',
            password: process.env.DB_PASSWORD,
        });
    
        const instance = new MySQLEvents(connection, {
            startAtEnd: true,
            excludedSchemas: {
                mysql: true,
            },
        });
    
        await instance.start();
    
        instance.addTrigger({
            name: 'monitoring . . .',
            expression: 'mobiusdb.cin',
            statement: MySQLEvents.STATEMENTS.ALL,
            onEvent: (event) => { 
    
                // these are for grafana
                var timeStamp = parseInt(event.timestamp);
                var msg = event.affectedRows[0].after.con;
                
                var jsonObject = parseRadar(msg.toString());
                // pos
                var pos = {
                    x: jsonObject.message.content !== null ? jsonObject.message.content.pos_x : null,
                    y: jsonObject.message.content !== null ? jsonObject.message.content.pos_y : null,
                    z: jsonObject.message.content !== null ? jsonObject.message.content.pos_z : null
                };
                // bpm
                var bpm = jsonObject.message.content !== null ? jsonObject.message.content.bpm : null;
                // hbr
                var hbr = jsonObject.message.content !== null ? jsonObject.message.content.hbr : null;
                // energy
                var eng = jsonObject.message.content !== null ? jsonObject.message.content.energy : null;
    
                console.log(timeStamp + ' : ' + JSON.stringify(pos), bpm, hbr, eng);
    
                // save to grafana
                // pos
                var sqlPos = 'INSERT INTO pos (pos_x, pos_y, pos_z, time) VALUES (?, ?, ?, ?)';
                var prmPos = [pos.x, pos.y, pos.z, timeStamp];
    
                // bpm
                var sqlBpm = 'INSERT INTO bpm (val, time) VALUES (?, ?)';
                var prmBpm = [bpm, timeStamp];
    
                // hbr
                var sqlHbr = 'INSERT INTO hbr (val, time) VALUES (?, ?)';
                var prmHbr = [hbr, timeStamp];
    
                // energy
                var sqlEng = 'INSERT INTO energy (val, time) VALUES (?, ?)';
                var prmEng = [eng, timeStamp];
    
                grafanaConn.query(sqlPos, prmPos, (e) => e ? console.log(e) : console.log('insert_pos'));
                if(bpm !== NaN)
                    grafanaConn.query(sqlBpm, prmBpm, (e) => e ? console.log(e) : console.log('insert_bpm'));
                if(hbr !== NaN)
                    grafanaConn.query(sqlHbr, prmHbr, (e) => e ? console.log(e) : console.log('insert_hbr'));
                if(eng !== NaN)
                    grafanaConn.query(sqlEng, prmEng, (e) => e ? console.log(e) : console.log('insert_eng'));
            },
        });
    
        instance.on(MySQLEvents.EVENTS.CONNECTION_ERROR, console.error);
        instance.on(MySQLEvents.EVENTS.ZONGJI_ERROR, console.error);
    };

addTrigger()안에서 event가 발생할 경우, timestamp'con' 컬럼에서 데이터를 가져옵니다. 가져온 데이터를 parse.js 에 있는 함수로 parsing 해주어 결과를 저장한 후, grafana 데이터베이스에 다시 저장해줍니다. raw하게 쿼리문을 이용하였습니다.


Grafana 설정하기

여기를 통해서 다운로드를 받으신 후 진행을 하셔도 되고, 도커(docker)가 다운로드된 상태라면 도커(docker)를 사용하는 방법도 있습니다.

Grafana 설정이 완료되었다면, 이제 listen할 데이터베이스를 설정해주면 됩니다. 그전에 Grafana에서 listen할 데이터베이스를 새로운 user가 접근할 수 있도록 MySQL 설정을 추가해주면 추가적인 에러가 발생하지 않는다고 합니다. 방법은 다음과 같습니다.

mysql> CREATE USER 'grafanaReader' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.03 sec)

mysql> GRANT SELECT ON mobiusdb.cin TO 'grafanaReader';
Query OK, 0 rows affected (0.00 sec)

위와같이 설정해두면 User Permission 문제가 발생할 일이 없습니다. 😁

그리고 사용할 데이터에 대한 데이터베이스와 테이블을 새롭게 만들었습니다. 우선 읽어올 수 있는 데이터를 이용하여 x,y,z 좌표, bpm, hbr 그리고 energy에 관한 테이블을 만들어 사용하는 예제입니다. 테이블을 총 4개이며, 결과창에는 4개의 대시보드가 출력되게 하였습니다.

앞서 설정한 <MySQL import 와 동일한 방법>으로 grafanadb.sql 파일을 import 해주시면 알맞은 테이블 4개가 생성됩니다.

설정을 마친 후 Grafana를 실행시켜 localhost:3000으로 접속하게되면, 초기 로그인 계정은

ID : admin / PW : admin

으로 로그인이 가능합니다. 로그인을 하게되면 변경해달라는 문구가 나오며 비밀번호를 변경해주세요 !

로그인을 하고, 왼쪽 바에서 톱니바퀴모양(Configuration) ⚙︎을 선택하고 Data Source로 이동합니다.


누르게 되면 'Add data source' 버튼을 눌러 MySQL을 검색해줍니다.

MySQL을 클릭하고 들어가면 안에 입력하는 칸을 모두 채우고

정보 입력

Save&Test 진행

'Save&Test'를 진행해 데이터베이스와 연동이 잘 이루어지는지 확인해봅니다 ! 잘 진행됐다면 Home으로 돌아가서 새로운 Dashboard를 추가해봅시다.😁


Create > Dashboard

MySQL 선택

Add new Panel

원하는 테이블, 컬럼 및 이름 설정


예시


💡실행방법

mobius-docker/mobius에서 아래와 같은 스크립트를 실행합니다.

npm run dev

위 스크립트를 실행하면 mosquitto, mobius 그리고 nCube-thyme가 실행됩니다.

위 스크립트가 모두 실행이 완료되면 그 후에, mobius-docker/mobius/mysql_radar에서 아래와 같이 스크립트를 실행해주세요.

npm run dev

위 스크립트를 실행하면 TAS-RADAR와 MySQL-listener가 실행됩니다.

가장 중요한 MySQL server가 실행되고 있는지 제일 먼저 확인해주시고 실행해주시길 바랍니다 !


이로써 하나의 TAS를 이용해서 Mobius Platform과 연동하는 예제를 진행해보았습니다.😁 들어오는 데이터를 가지고 디바이스제어 등 여러가지를 할 수 있습니다.

감사합니다. 😁

seunghwanly/mobius-docker

profile
잡동사니 😁

0개의 댓글