public synchronized void create()

in oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/MeterSystem.java [143:260]


    public synchronized <T> void create(String metricsName,
                                        String functionName,
                                        ScopeType type,
                                        Class<T> dataType) throws IllegalArgumentException {
        /**
         * Create a new meter class dynamically.
         */
        final Class<? extends AcceptableValue> meterFunction = functionRegister.get(functionName);

        if (meterFunction == null) {
            throw new IllegalArgumentException("Function " + functionName + " can't be found.");
        }

        boolean foundDataType = false;
        String acceptance = null;
        for (final Type genericInterface : meterFunction.getGenericInterfaces()) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
                if (parameterizedType.getRawType().getTypeName().equals(AcceptableValue.class.getName())) {
                    Type[] arguments = parameterizedType.getActualTypeArguments();
                    if (arguments[0].equals(dataType)) {
                        foundDataType = true;
                    } else {
                        acceptance = arguments[0].getTypeName();
                    }
                }
                if (foundDataType) {
                    break;
                }
            }
        }
        if (!foundDataType) {
            throw new IllegalArgumentException("Function " + functionName
                                                   + " requires <" + acceptance + "> in AcceptableValue"
                                                   + " but using " + dataType.getName() + " in the creation");
        }

        final CtClass parentClass;
        try {
            parentClass = classPool.get(meterFunction.getCanonicalName());
            if (!Metrics.class.isAssignableFrom(meterFunction)) {
                throw new IllegalArgumentException(
                    "Function " + functionName + " doesn't inherit from Metrics.");
            }
        } catch (NotFoundException e) {
            throw new IllegalArgumentException("Function " + functionName + " can't be found by javaassist.");
        }
        final String className = formatName(metricsName);

        /**
         * Check whether the metrics class is already defined or not
         */
        try {
            CtClass existingMetric = classPool.get(METER_CLASS_PACKAGE + className);
            if (existingMetric.getSuperclass() != parentClass || type != meterPrototypes.get(metricsName)
                                                                                        .getScopeType()) {
                throw new IllegalArgumentException(
                    metricsName + " has been defined, but calculate function or/are scope type is/are different.");
            }
            log.info("Metric {} is already defined, so skip the metric creation.", metricsName);
            return;
        } catch (NotFoundException e) {
        }

        CtClass metricsClass = classPool.makeClass(METER_CLASS_PACKAGE + className, parentClass);

        /**
         * Create empty construct
         */
        try {
            CtConstructor defaultConstructor = CtNewConstructor.make(
                "public " + className + "() {}", metricsClass);
            metricsClass.addConstructor(defaultConstructor);
        } catch (CannotCompileException e) {
            log.error("Can't add empty constructor in " + className + ".", e);
            throw new UnexpectedException(e.getMessage(), e);
        }

        /**
         * Generate `AcceptableValue<T> createNew()` method.
         */
        try {
            metricsClass.addMethod(CtNewMethod.make(
                ""
                    + "public org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue createNew() {"
                    + "    org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue meterVar = new " + METER_CLASS_PACKAGE + className + "();"
                    + "    ((org.apache.skywalking.oap.server.core.analysis.meter.Meter)meterVar).initMeta(\"" + metricsName + "\", " + type.getScopeId() + ");"
                    + "    return meterVar;"
                    + " }"
                , metricsClass));
        } catch (CannotCompileException e) {
            log.error("Can't generate createNew method for " + className + ".", e);
            throw new UnexpectedException(e.getMessage(), e);
        }

        Class targetClass;
        try {
            if (SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_1_8)) {
                targetClass = metricsClass.toClass(MeterSystem.class.getClassLoader(), null);
            } else {
                targetClass = metricsClass.toClass(MeterClassPackageHolder.class);
            }
            AcceptableValue prototype = (AcceptableValue) targetClass.newInstance();
            meterPrototypes.put(metricsName, new MeterDefinition(type, prototype, dataType));

            log.debug("Generate metrics class, " + metricsClass.getName());

            MetricsStreamProcessor.getInstance().create(
                manager,
                new StreamDefinition(
                    metricsName, type.getScopeId(), prototype.builder(), MetricsStreamProcessor.class),
                targetClass
            );
        } catch (CannotCompileException | IllegalAccessException | InstantiationException | StorageException e) {
            log.error("Can't compile/load/init " + className + ".", e);
            throw new UnexpectedException(e.getMessage(), e);
        }
    }