Skip to content

Commit

Permalink
made annotation analyzer configurable and moved to custom analyzer ex…
Browse files Browse the repository at this point in the history
…ample
  • Loading branch information
xndlnk committed Jun 1, 2019
1 parent 254aee6 commit f7d4624
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 41 deletions.
5 changes: 5 additions & 0 deletions README-v1-draft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# TADIS - Tool for Architecture Discovery

- [tadis-analyzer](sources/tadis-analyzer) - analyzer backend
- [tadis-analyzer-custom-example](sources/tadis-analyzer-custom-example) - example customization of tadis-analyzer
- [tadis-viewer-d3](sources/tadis-viewer-d3) - web-frontend based on D3
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Module } from '@nestjs/common'
import { CollectorService, ConfigModule, CollectorController, SourceCodeAnalysisModule } from 'acmi-analyzer'

import {
CollectorService, ConfigModule, CollectorController, SourceCodeAnalysisModule,
KubernetesModule, RabbitMqModule, TransformerModule
} from 'acmi-analyzer'

import { CustomCollectorService } from './CustomCollector.service'

Expand All @@ -11,7 +15,10 @@ const customCollectorProvider = {
@Module({
imports: [
ConfigModule,
SourceCodeAnalysisModule
KubernetesModule,
RabbitMqModule,
SourceCodeAnalysisModule,
TransformerModule
],
controllers: [
CollectorController
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,74 @@
import { Injectable } from '@nestjs/common'
import { System, MicroService } from 'acmi-analyzer'

import {
System, MicroService, Metadata, KubernetesCollectorService, RabbitMqCollectorService,
FeignClientsFromSourceCodeProducer, AnnotationAnalyzer, SourceLocationDecorator,
ExcludedNodesRemover, MicroserviceWithMessageExchangeMerger, CabinetTransformer, ElementMapping, GitStorageService, ConfigService
} from 'acmi-analyzer'

@Injectable()
export class CustomCollectorService {

constructor(
private readonly kubernetesCollector: KubernetesCollectorService,
private readonly rabbitMqCollector: RabbitMqCollectorService,
private readonly feignClientsFromSourceCodeProducer: FeignClientsFromSourceCodeProducer,
private readonly annotationAnalyzer: AnnotationAnalyzer,
private readonly sourceLocationDecorator: SourceLocationDecorator,
private readonly excludedNodesRemover: ExcludedNodesRemover,
private readonly microserviceWithMessageExchangeMerger: MicroserviceWithMessageExchangeMerger,
private readonly cabinetTransformer: CabinetTransformer,
private readonly gitStorage: GitStorageService,
private readonly configService: ConfigService
) { }

public async getAllMicroservices(): Promise<MicroService[]> {
return []
return this.kubernetesCollector.getAllMicroservices()
}

public async getSystem(): Promise<System> {
return new System('my')
let system = new System('')

system = await this.getAllMicroservicesFromSourceFolder()
// system = await this.kubernetesCollector.transform(system)
// system = await this.rabbitMqCollector.transform(system)

system = await this.feignClientsFromSourceCodeProducer.transform(system)

const elementMappings: ElementMapping[] = [
{
elementName: 'sendToExchange',
nodeTypeToCreate: 'MessageExchange',
nodeTypeDirection: 'target',
edgeType: 'AsyncEventFlow'
},
{
elementName: 'receiveFromExchange',
nodeTypeToCreate: 'MessageExchange',
nodeTypeDirection: 'source',
edgeType: 'AsyncEventFlow'
}
]
system = await this.annotationAnalyzer.transform(system, 'EventProcessor', elementMappings)
system = await this.sourceLocationDecorator.transform(system)

system = await this.excludedNodesRemover.transform(system)
system = await this.microserviceWithMessageExchangeMerger.transform(system)
system = await this.cabinetTransformer.transform(system)

return system
}

private async getAllMicroservicesFromSourceFolder(): Promise<System> {
const storageStatus = await this.gitStorage.getStorageStatus()
const metadata: Metadata = {
transformer: 'custom git sources to microservices',
context: this.configService.getSourceFolder()
}
const system = new System('source')
storageStatus.forEach(status => {
system.addMicroService(status.name, undefined, metadata)
})
return system
}
}
2 changes: 1 addition & 1 deletion sources/acmi-analyzer/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# acmi-analyzer

The acmi-analyzer is the analysis part of the architecture analyzer for microservice systems (acmi). It can discover the architecture of a microservice system by collecting information about the system from different sources.
The acmi-analyzer can discover the architecture of a microservice system by collecting information about the system from different sources.

## Installation

Expand Down
6 changes: 0 additions & 6 deletions sources/acmi-analyzer/src/collector/Collector.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { KubernetesCollectorService } from '../kubernetes/collector/KubernetesCo

import { RabbitMqModule } from '../rabbitmq/rabbitmq.module'
import { RabbitMqCollectorService } from '../rabbitmq/collector/RabbitMqCollector.service'
import { AnnotationAnalyzer } from './java-source/AnnotationAnalyzer.service'
import { System } from 'src/model/ms'
import { SourceLocationDecorator } from '../source-code-analysis/git/SourceLocationDecorator.service'

Expand Down Expand Up @@ -46,10 +45,6 @@ describe(CollectorService.name, () => {
const spyOnFeignProducer = jest.spyOn(feignProducer, 'transform')
spyOnFeignProducer.mockImplementation(async(system) => system)

const annotationAnalyzer = app.get<AnnotationAnalyzer>(AnnotationAnalyzer)
const spyOnAnnotationAnalyzer = jest.spyOn(annotationAnalyzer, 'transform')
spyOnAnnotationAnalyzer.mockImplementation(async(system) => system)

const excludedNodesRemover = app.get<ExcludedNodesRemover>(ExcludedNodesRemover)
const spyOnExcludedNodesRemover = jest.spyOn(excludedNodesRemover, 'transform')
spyOnExcludedNodesRemover.mockImplementation(async(system) => system)
Expand All @@ -69,7 +64,6 @@ describe(CollectorService.name, () => {
expect(spyOnRabbitMqCollector).toHaveBeenCalled()

expect(spyOnFeignProducer).toHaveBeenCalled()
expect(spyOnAnnotationAnalyzer).toHaveBeenCalled()

expect(spyOnExcludedNodesRemover).toHaveBeenCalled()
expect(spyOnCabinetLabelsTransformer).toHaveBeenCalled()
Expand Down
3 changes: 1 addition & 2 deletions sources/acmi-analyzer/src/collector/Collector.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Injectable } from '@nestjs/common'
import { ModuleRef } from '@nestjs/core'
import * as _ from 'lodash'

import { System, MicroService } from '../model/ms'
import { ModuleRef } from '@nestjs/core'
import { KubernetesCollectorService } from '../kubernetes/collector/KubernetesCollector.service'
import { RabbitMqCollectorService } from '../rabbitmq/collector/RabbitMqCollector.service'

Expand All @@ -26,7 +26,6 @@ export class CollectorService {
system = await this.rabbitMqCollector.transform(system)

system = await this.getProvider('FeignClientsFromSourceCodeProducer').transform(system)
system = await this.getProvider('AnnotationAnalyzer').transform(system)
system = await this.getProvider('SourceLocationDecorator').transform(system)

// INFO: actually this is no collector. we keep here for compatibility reasons
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ConfigService } from '../../config/Config.service'

import { System, AsyncEventFlow } from '../../model/ms'
import { verifyEachContentHasTransformer } from '../../test/verifiers'
import { AnnotationAnalyzer } from './AnnotationAnalyzer.service'
import { AnnotationAnalyzer, ElementMapping } from './AnnotationAnalyzer.service'

describe(AnnotationAnalyzer.name, () => {
let app: TestingModule
Expand All @@ -25,6 +25,21 @@ describe(AnnotationAnalyzer.name, () => {
}).compile()
})

const elementMappings: ElementMapping[] = [
{
elementName: 'sendToExchange',
nodeTypeToCreate: 'MessageExchange',
nodeTypeDirection: 'target',
edgeType: 'AsyncEventFlow'
},
{
elementName: 'receiveFromExchange',
nodeTypeToCreate: 'MessageExchange',
nodeTypeDirection: 'source',
edgeType: 'AsyncEventFlow'
}
]

it('creates an async info flow for multiple annotations in the same file', async() => {
const config = app.get<ConfigService>(ConfigService)
jest.spyOn(config, 'getSourceFolder').mockImplementation(
Expand All @@ -35,7 +50,7 @@ describe(AnnotationAnalyzer.name, () => {
inputSystem.addMicroService('service1')

const transformer = app.get<AnnotationAnalyzer>(AnnotationAnalyzer)
const outputSystem = await transformer.transform(inputSystem)
const outputSystem = await transformer.transform(inputSystem, 'EventProcessor', elementMappings)

expect(outputSystem.findMicroService('service1')).toBeDefined()
expect(outputSystem.findMessageExchange('target-exchange-X')).toBeDefined()
Expand Down Expand Up @@ -63,7 +78,7 @@ describe(AnnotationAnalyzer.name, () => {
inputSystem.addMessageExchange('source-exchange-X')

const transformer = app.get<AnnotationAnalyzer>(AnnotationAnalyzer)
const outputSystem = await transformer.transform(inputSystem)
const outputSystem = await transformer.transform(inputSystem, 'EventProcessor', elementMappings)

expect(outputSystem.findMicroService('service1')).toBeDefined()
expect(outputSystem.nodes.filter(node => node.getName() === 'source-exchange-X')).toHaveLength(1)
Expand All @@ -80,7 +95,7 @@ describe(AnnotationAnalyzer.name, () => {
const inputSystem = new System('test')

const transformer = app.get<AnnotationAnalyzer>(AnnotationAnalyzer)
const outputSystem = await transformer.transform(inputSystem)
const outputSystem = await transformer.transform(inputSystem, 'EventProcessor', elementMappings)

expect(outputSystem.findMicroService('service1')).toBeUndefined()
expect(outputSystem.findMessageExchange('target-exchange')).toBeUndefined()
Expand All @@ -96,7 +111,7 @@ describe(AnnotationAnalyzer.name, () => {
inputSystem.addMicroService('service1')

const transformer = app.get<AnnotationAnalyzer>(AnnotationAnalyzer)
const outputSystem = await transformer.transform(inputSystem)
const outputSystem = await transformer.transform(inputSystem, 'EventProcessor', elementMappings)

expect(outputSystem.findMicroService('service1')).toBeDefined()
expect(outputSystem.findMessageExchange('source-exchange-X')).toBeDefined()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ export class AnnotationAnalyzer {
private readonly config: ConfigService
) { }

public async transform(system: System): Promise<System> {
await this.transformSourcesInPath(system, this.config.getSourceFolder())
public async transform(system: System, annotation: string, elementMappings: ElementMapping[]): Promise<System> {
await this.transformSourcesInPath(system, this.config.getSourceFolder(), annotation, elementMappings)
return system
}

private async transformSourcesInPath(system: System, path: string) {
private async transformSourcesInPath(system: System, path: string, annotation: string, elementMappings: ElementMapping[]) {
this.logger.log('scanning java files in ' + path)
const javaFiles = await findFiles(path, '.java')
this.logger.log('found ' + javaFiles.length + ' java files')
Expand All @@ -42,28 +42,13 @@ export class AnnotationAnalyzer {
} else {
const fileContent = fs.readFileSync(file, 'utf8')

const elementMappings: ElementMapping[] = [
{
elementName: 'sendToExchange',
nodeTypeToCreate: 'MessageExchange',
nodeTypeDirection: 'target',
edgeType: 'AsyncEventFlow'
},
{
elementName: 'receiveFromExchange',
nodeTypeToCreate: 'MessageExchange',
nodeTypeDirection: 'source',
edgeType: 'AsyncEventFlow'
}
]

transformEachAnnotation(system, service, 'EventProcessor', fileContent, elementMappings)
transformEachAnnotation(system, service, annotation, fileContent, elementMappings)
}
})
}
}

type ElementMapping = {
export type ElementMapping = {
/**
* name of the annotation element that defines the node name as its value
*/
Expand Down
4 changes: 2 additions & 2 deletions sources/acmi-analyzer/src/collector/transformer.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CabinetTransformer } from './generic-transformer/CabinetTransformer'
import { MicroserviceWithMessageExchangeMerger } from './generic-transformer/MicroserviceWithMessageExchangeMerger'
import { ConfigModule } from '../config/config.module'
import { SourceCodeAnalysisModule } from '../source-code-analysis/SourceCodeAnalysis.module'
import { AnnotationAnalyzer } from './java-source/AnnotationAnalyzer.service'
import { AnnotationAnalyzer, ElementMapping } from './java-source/AnnotationAnalyzer.service'

@Module({
imports: [
Expand All @@ -33,6 +33,6 @@ import { AnnotationAnalyzer } from './java-source/AnnotationAnalyzer.service'
class TransformerModule { }

export {
TransformerModule, ExcludedNodesRemover, FeignClientsFromSourceCodeProducer, AnnotationAnalyzer,
TransformerModule, ExcludedNodesRemover, FeignClientsFromSourceCodeProducer, AnnotationAnalyzer, ElementMapping,
CabinetTransformer, MicroserviceWithMessageExchangeMerger
}

0 comments on commit f7d4624

Please sign in to comment.